Skip to content

Commit a3198c3

Browse files
committed
Created JSON Compilation Database Generator preference page and set file
generation on false by default. Added JUnit test to test the generation of the file
1 parent e6fb475 commit a3198c3

File tree

9 files changed

+334
-12
lines changed

9 files changed

+334
-12
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2019, 2020 Marc-Andre Laperle.
3+
*
4+
* This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License 2.0
6+
* which accompanies this distribution, and is available at
7+
* https://www.eclipse.org/legal/epl-2.0/
8+
*
9+
* SPDX-License-Identifier: EPL-2.0
10+
*******************************************************************************/
11+
package org.eclipse.cdt.managedbuilder.core.tests;
12+
13+
import static org.junit.jupiter.api.Assertions.assertEquals;
14+
import static org.junit.jupiter.api.Assertions.assertFalse;
15+
import static org.junit.jupiter.api.Assertions.assertTrue;
16+
17+
import java.io.FileReader;
18+
import java.io.IOException;
19+
20+
import org.eclipse.cdt.managedbuilder.core.ManagedBuilderCorePlugin;
21+
import org.eclipse.cdt.managedbuilder.core.jsoncdb.CompilationDatabaseInformation;
22+
import org.eclipse.cdt.managedbuilder.testplugin.AbstractBuilderTest;
23+
import org.eclipse.cdt.managedbuilder.testplugin.ManagedBuildTestHelper;
24+
import org.eclipse.core.resources.IFile;
25+
import org.eclipse.core.resources.IProject;
26+
import org.eclipse.core.resources.IncrementalProjectBuilder;
27+
import org.eclipse.core.runtime.CoreException;
28+
import org.eclipse.core.runtime.preferences.InstanceScope;
29+
import org.eclipse.jface.preference.IPreferenceStore;
30+
import org.eclipse.ui.preferences.ScopedPreferenceStore;
31+
import org.junit.Test;
32+
33+
import com.google.gson.Gson;
34+
import com.google.gson.JsonArray;
35+
import com.google.gson.JsonElement;
36+
import com.google.gson.JsonIOException;
37+
38+
public class CompilationDatabaseGenerationTest extends AbstractBuilderTest {
39+
40+
/**
41+
* Tests generation of compile_commands.json in "build" folder
42+
* @throws CoreException
43+
*/
44+
@Test
45+
public void testCompilationDatabaseGeneration() throws CoreException {
46+
setWorkspace("regressions");
47+
final IProject app = loadProject("helloworldC");
48+
isGenerateFileOptionEnabled(true);
49+
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
50+
IFile compilationDatabase = app.getFile("build/compile_commands.json");
51+
assertTrue(compilationDatabase.exists());
52+
}
53+
54+
/**
55+
* Tests format for compile_commands.json. JSON array is expected, containing an element for the c file
56+
* @throws JsonIOException
57+
* @throws CoreException
58+
*/
59+
@Test
60+
public void testJsonFormat() throws JsonIOException, CoreException {
61+
setWorkspace("regressions");
62+
final IProject app = loadProject("helloworldC");
63+
isGenerateFileOptionEnabled(true);
64+
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
65+
IFile commandsFile = app.getFile("build/compile_commands.json");
66+
if (commandsFile.exists()) {
67+
68+
try (FileReader reader = new FileReader(commandsFile.getLocation().toFile())) {
69+
Gson gson = new Gson();
70+
JsonArray jsonArray = gson.fromJson(reader, JsonArray.class);
71+
System.out.println(jsonArray);
72+
for (JsonElement element : jsonArray) {
73+
CompilationDatabaseInformation compileCommand = gson.fromJson(element,
74+
CompilationDatabaseInformation.class);
75+
76+
assertTrue(compileCommand.directory() != null && !compileCommand.directory().isEmpty());
77+
assertTrue(compileCommand.command() != null && !compileCommand.command().isEmpty());
78+
assertTrue(compileCommand.file() != null && !compileCommand.file().isEmpty());
79+
assertTrue(compileCommand.file().endsWith("src/helloworldC.c"));
80+
}
81+
82+
} catch (IOException e) {
83+
assertTrue(false);
84+
}
85+
86+
}
87+
}
88+
89+
/**
90+
* Test that compile_commands.json is correctly generated when more than one .c file is present as a source file
91+
* @throws CoreException
92+
*/
93+
@Test
94+
public void testMultipleFiles() throws CoreException {
95+
setWorkspace("regressions");
96+
final IProject app = loadProject("helloworldC");
97+
IFile aFile = ManagedBuildTestHelper.createFile(app, "src/newFile.c");
98+
isGenerateFileOptionEnabled(true);
99+
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
100+
IFile commandsFile = app.getFile("build/compile_commands.json");
101+
int numberOfElementsFound = 0;
102+
boolean helloworldCIsPresent = false;
103+
boolean newFileIsPresent = false;
104+
try (FileReader reader = new FileReader(commandsFile.getLocation().toFile())) {
105+
Gson gson = new Gson();
106+
JsonArray jsonArray = gson.fromJson(reader, JsonArray.class);
107+
System.out.println(jsonArray);
108+
for (JsonElement element : jsonArray) {
109+
CompilationDatabaseInformation compileCommand = gson.fromJson(element,
110+
CompilationDatabaseInformation.class);
111+
numberOfElementsFound++;
112+
if (compileCommand.file().endsWith("helloworldC.c")) {
113+
helloworldCIsPresent = true;
114+
}
115+
if (compileCommand.file().endsWith("newFile.c")) {
116+
newFileIsPresent = true;
117+
}
118+
}
119+
assertEquals(2, numberOfElementsFound);
120+
assertTrue(helloworldCIsPresent);
121+
assertTrue(newFileIsPresent);
122+
} catch (IOException e) {
123+
assertTrue(false);
124+
}
125+
126+
}
127+
128+
/**
129+
* Tests that cpp files are handled by compile_commands.json file generator
130+
* @throws CoreException
131+
*/
132+
@Test
133+
public void isCPPFileAllowed() throws CoreException {
134+
setWorkspace("regressions");
135+
final IProject app = loadProject("helloworldCPP");
136+
isGenerateFileOptionEnabled(true);
137+
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
138+
System.out.println(app.getLocation());
139+
IFile commandsFile = app.getFile("build/compile_commands.json");
140+
if (commandsFile.exists()) {
141+
142+
try (FileReader reader = new FileReader(commandsFile.getLocation().toFile())) {
143+
Gson gson = new Gson();
144+
JsonArray jsonArray = gson.fromJson(reader, JsonArray.class);
145+
System.out.println(jsonArray);
146+
for (JsonElement element : jsonArray) {
147+
CompilationDatabaseInformation compileCommand = gson.fromJson(element,
148+
CompilationDatabaseInformation.class);
149+
150+
assertTrue(compileCommand.directory() != null && !compileCommand.directory().isEmpty());
151+
assertTrue(compileCommand.command() != null && !compileCommand.command().isEmpty());
152+
assertTrue(compileCommand.file() != null && !compileCommand.file().isEmpty());
153+
assertTrue(compileCommand.file().endsWith("src/helloworldCPP.cpp"));
154+
}
155+
156+
} catch (IOException e) {
157+
assertTrue(false);
158+
}
159+
}
160+
}
161+
162+
/**
163+
* Tests that compilation database is not generated when feature is disabled
164+
* @throws CoreException
165+
*/
166+
@Test
167+
public void testCompilationDatabaseGenerationNotEnabled() throws CoreException {
168+
setWorkspace("regressions");
169+
final IProject app = loadProject("helloworldC");
170+
isGenerateFileOptionEnabled(false);
171+
app.build(IncrementalProjectBuilder.FULL_BUILD, null);
172+
IFile compilationDatabase = app.getFile("build/compile_commands.json");
173+
assertFalse(compilationDatabase.exists());
174+
}
175+
176+
public static boolean isGenerateFileOptionEnabled(boolean value) {
177+
try {
178+
IPreferenceStore preferenceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE,
179+
"org.eclipse.cdt.managedbuilder.ui"); //$NON-NLS-1$
180+
preferenceStore.setDefault("generateFile", value);
181+
return preferenceStore.getBoolean("generateFile");
182+
} catch (Exception e) {
183+
ManagedBuilderCorePlugin.log(e);
184+
}
185+
return false;
186+
}
187+
}

build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/core/jsoncdb/generator/CompilationDatabaseContributionManager.java

+11-9
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,17 @@
3232
private static final String ATTRIB_TOOLCHAIN_ID = "toolchainID"; //$NON-NLS-1$
3333
private static final String ID_COMPILATIONDATABASE = "compilationDatabase"; //$NON-NLS-1$
3434
private static final String EXTENSION_ID = "compilationDatabaseContributor"; //$NON-NLS-1$
35+
/**
36+
* Map of tool chain IDs (see {@link IToolChain#getId()} to
37+
* loaded instances of {@link ICompilationDatabaseContributor}
38+
*/
3539
@NonNull
36-
private final Map<String, ICompilationDatabaseContributor> loadedInstances;
37-
private final Map<String, IConfigurationElement> factoryExtensions;
40+
private final Map<String, ICompilationDatabaseContributor> loadedInstances = new HashMap<>();
41+
/**
42+
* Map of tool chain IDs (see {@link IToolChain#getId()} to
43+
* extension point information for the compilationDatabaseContributor extension.
44+
*/
45+
private final Map<String, IConfigurationElement> factoryExtensions = new HashMap<>();
3846

3947
private class EmptyCompilationDatabaseContributor implements ICompilationDatabaseContributor {
4048

@@ -47,8 +55,6 @@ private class EmptyCompilationDatabaseContributor implements ICompilationDatabas
4755
private static CompilationDatabaseContributionManager instance;
4856

4957
private CompilationDatabaseContributionManager() {
50-
this.factoryExtensions = new HashMap<>();
51-
this.loadedInstances = new HashMap<>();
5258
initalise();
5359
}
5460

@@ -60,8 +66,6 @@ public static synchronized CompilationDatabaseContributionManager getInstance()
6066
}
6167

6268
private void initalise() {
63-
Map<String, IConfigurationElement> loadedExtension = new HashMap<>();
64-
6569
IExtensionPoint extension = Platform.getExtensionRegistry().getExtensionPoint(
6670
"org.eclipse.cdt.managedbuilder.core", CompilationDatabaseContributionManager.EXTENSION_ID); //$NON-NLS-1$
6771
if (extension != null) {
@@ -75,14 +79,12 @@ private void initalise() {
7579
String className = configElement
7680
.getAttribute(CompilationDatabaseContributionManager.ATTRIB_RUNNER);
7781
if (toolchainId != null && className != null) {
78-
loadedExtension.put(toolchainId, configElement);
82+
factoryExtensions.put(toolchainId, configElement);
7983
}
8084
}
8185
}
8286
}
8387
}
84-
85-
this.factoryExtensions.putAll(loadedExtension);
8688
}
8789

8890
/**

build/org.eclipse.cdt.managedbuilder.core/src/org/eclipse/cdt/managedbuilder/internal/core/CommonBuilder.java

+19-2
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@
8686
import org.eclipse.core.runtime.SubProgressMonitor;
8787
import org.eclipse.core.runtime.jobs.ISchedulingRule;
8888
import org.eclipse.core.runtime.jobs.Job;
89+
import org.eclipse.core.runtime.preferences.InstanceScope;
90+
import org.eclipse.jface.preference.IPreferenceStore;
91+
import org.eclipse.ui.preferences.ScopedPreferenceStore;
8992

9093
public class CommonBuilder extends ACBuilder implements IIncrementalProjectBuilder2 {
9194

@@ -94,6 +97,7 @@ public class CommonBuilder extends ACBuilder implements IIncrementalProjectBuild
9497
private static final String NEWLINE = System.getProperty("line.separator"); //$NON-NLS-1$
9598
private static final String TRACE_FOOTER = "]: "; //$NON-NLS-1$
9699
private static final String TRACE_HEADER = "GeneratedmakefileBuilder trace ["; //$NON-NLS-1$
100+
private static final String COMPILATION_DATABASE_ENABLEMENT = "generateFile"; //$NON-NLS-1$
97101
public static boolean VERBOSE = false;
98102

99103
private static final int PROGRESS_MONITOR_SCALE = 100;
@@ -506,8 +510,10 @@ private IProject[] build(int kind, IProject project, IBuilder[] builders, boolea
506510
}
507511

508512
for (int i = 0; i < num; i++) {
509-
CompilationDatabaseGenerator generator = new CompilationDatabaseGenerator(getProject(), activeCfg);
510-
generator.generate();
513+
if (isGenerateFileOptionEnabled()) {
514+
CompilationDatabaseGenerator generator = new CompilationDatabaseGenerator(getProject(), activeCfg);
515+
generator.generate();
516+
}
511517
//bug 219337
512518
if (kind == INCREMENTAL_BUILD || kind == AUTO_BUILD) {
513519
if (buildConfigResourceChanges()) { //only build projects with project resource changes
@@ -1378,4 +1384,15 @@ public ISchedulingRule getRule(int trigger, Map args) {
13781384
// Success!
13791385
return null;
13801386
}
1387+
1388+
public static boolean isGenerateFileOptionEnabled() {
1389+
try {
1390+
IPreferenceStore preferenceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE,
1391+
"org.eclipse.cdt.managedbuilder.ui"); //$NON-NLS-1$
1392+
return preferenceStore.getBoolean(COMPILATION_DATABASE_ENABLEMENT);
1393+
} catch (Exception e) {
1394+
ManagedBuilderCorePlugin.log(e);
1395+
}
1396+
return false;
1397+
}
13811398
}

build/org.eclipse.cdt.managedbuilder.ui/META-INF/MANIFEST.MF

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %pluginName
44
Bundle-SymbolicName: org.eclipse.cdt.managedbuilder.ui; singleton:=true
5-
Bundle-Version: 9.4.0.qualifier
5+
Bundle-Version: 9.4.100.qualifier
66
Bundle-Activator: org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin
77
Bundle-Vendor: %providerName
88
Bundle-Localization: plugin

build/org.eclipse.cdt.managedbuilder.ui/plugin.xml

+9
Original file line numberDiff line numberDiff line change
@@ -917,5 +917,14 @@
917917
label="%CDTToolchainProperty.keyword.toolchain2">
918918
</keyword>
919919
</extension>
920+
<extension
921+
point="org.eclipse.ui.preferencePages">
922+
<page
923+
category="org.eclipse.cdt.ui.preferences.BuildSettings"
924+
class="org.eclipse.cdt.managedbuilder.ui.compilationdatabase.JsonCdbGeneratorPreferencePage"
925+
id="org.eclipse.cdt.managedbuilder.ui.compilationdatabase.JsonCdbPreferencePage"
926+
name="JSON Compilation Database Generator">
927+
</page>
928+
</extension>
920929

921930
</plugin>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/********************************************************************************
2+
* Copyright (c) 2023, 2024 Renesas Electronics Corp. and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
********************************************************************************/
10+
package org.eclipse.cdt.managedbuilder.ui.compilationdatabase;
11+
12+
import org.eclipse.cdt.managedbuilder.ui.properties.ManagedBuilderUIPlugin;
13+
import org.eclipse.jface.preference.IPreferenceStore;
14+
import org.eclipse.jface.preference.PreferencePage;
15+
import org.eclipse.swt.SWT;
16+
import org.eclipse.swt.layout.FillLayout;
17+
import org.eclipse.swt.layout.GridData;
18+
import org.eclipse.swt.layout.GridLayout;
19+
import org.eclipse.swt.widgets.Button;
20+
import org.eclipse.swt.widgets.Composite;
21+
import org.eclipse.swt.widgets.Control;
22+
import org.eclipse.swt.widgets.Group;
23+
import org.eclipse.ui.IWorkbench;
24+
import org.eclipse.ui.IWorkbenchPreferencePage;
25+
26+
/**
27+
* Preference page for JSON Compilation Database Generator.
28+
*/
29+
public class JsonCdbGeneratorPreferencePage extends PreferencePage implements IWorkbenchPreferencePage {
30+
private static final String ENABLE_FILE_GENERATION = "generateFile"; //$NON-NLS-1$
31+
private Button generateFileCheckbox;
32+
private IPreferenceStore preferenceStore;
33+
34+
public JsonCdbGeneratorPreferencePage() {
35+
preferenceStore = ManagedBuilderUIPlugin.getDefault().getPreferenceStore();
36+
}
37+
38+
@Override
39+
protected Control createContents(Composite parent) {
40+
final Composite composite = new Composite(parent, SWT.NONE);
41+
composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
42+
composite.setLayout(new GridLayout(1, false));
43+
Group cdbGeneratorOptions = new Group(composite, SWT.NONE);
44+
cdbGeneratorOptions.setLayout(new FillLayout(SWT.HORIZONTAL));
45+
cdbGeneratorOptions.setText(Messages.JsonCdbGeneratorPreferencePage_description);
46+
cdbGeneratorOptions.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
47+
generateFileCheckbox = new Button(cdbGeneratorOptions, SWT.CHECK);
48+
generateFileCheckbox.setSelection(preferenceStore.getBoolean(ENABLE_FILE_GENERATION));
49+
generateFileCheckbox.setText(Messages.JsonCdbGeneratorPreferencePage_generateCompilationdatabase);
50+
generateFileCheckbox.addListener(SWT.Selection, e -> {
51+
boolean newValue = generateFileCheckbox.getSelection();
52+
preferenceStore.setValue(ENABLE_FILE_GENERATION, newValue);
53+
});
54+
return composite;
55+
}
56+
57+
/**
58+
* Initializes the default values of this page in the preference bundle.
59+
*/
60+
@Override
61+
protected void performDefaults() {
62+
super.performDefaults();
63+
preferenceStore.setDefault(ENABLE_FILE_GENERATION, false);
64+
}
65+
66+
@Override
67+
public void init(IWorkbench workbench) {
68+
}
69+
70+
}

0 commit comments

Comments
 (0)