Skip to content

Commit dc40859

Browse files
committed
[#227] Refactor ClangdConfigurationManager
- Fix unit tests fixes #227
1 parent 67c4d24 commit dc40859

File tree

5 files changed

+66
-41
lines changed

5 files changed

+66
-41
lines changed

bundles/org.eclipse.cdt.lsp.clangd/META-INF/MANIFEST.MF

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ Require-Bundle: org.eclipse.cdt.lsp;bundle-version="0.0.0",
3232
org.eclipse.ui.workbench.texteditor;bundle-version="0.0.0",
3333
org.eclipse.core.variables
3434
Service-Component: OSGI-INF/org.eclipse.cdt.lsp.clangd.BuiltinClangdOptionsDefaults.xml,
35-
OSGI-INF/org.eclipse.cdt.lsp.clangd.ClangdConfigurationManager.xml,
35+
OSGI-INF/org.eclipse.cdt.lsp.clangd.ClangdConfigurationFileManager.xml,
3636
OSGI-INF/org.eclipse.cdt.lsp.clangd.DefaultCProjectChangeMonitor.xml,
3737
OSGI-INF/org.eclipse.cdt.lsp.internal.clangd.ClangdConfigurationAccess.xml,
3838
OSGI-INF/org.eclipse.cdt.lsp.internal.clangd.ClangdFallbackManager.xml,
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.cdt.lsp.clangd.ClangdConfigurationManager">
2+
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.eclipse.cdt.lsp.clangd.ClangdConfigurationFileManager">
33
<property name="service.ranking" type="Integer" value="0"/>
44
<service>
55
<provide interface="org.eclipse.cdt.lsp.clangd.ClangdCProjectDescriptionListener"/>
66
</service>
7-
<implementation class="org.eclipse.cdt.lsp.clangd.ClangdConfigurationManager"/>
7+
<implementation class="org.eclipse.cdt.lsp.clangd.ClangdConfigurationFileManager"/>
88
</scr:component>

bundles/org.eclipse.cdt.lsp.clangd/src/org/eclipse/cdt/lsp/clangd/ClangdCProjectDescriptionListener.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
/**
2121
* Vendors can implement this interface as OSGi service
2222
* with a service.ranking property > 0 to implement custom behavior
23-
* and to replace the {@link ClangdConfigurationManager}
23+
* and to replace the {@link ClangdConfigurationFileManager}
2424
*/
2525
public interface ClangdCProjectDescriptionListener {
2626
String CLANGD_CONFIG_FILE_NAME = ".clangd"; //$NON-NLS-1$
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@
5050
* This class can be extended by vendors.
5151
*/
5252
@Component(property = { "service.ranking:Integer=0" })
53-
public class ClangdConfigurationManager implements ClangdCProjectDescriptionListener {
53+
public class ClangdConfigurationFileManager implements ClangdCProjectDescriptionListener {
5454
private static final String COMPILE_FLAGS = "CompileFlags"; //$NON-NLS-1$
5555
private static final String COMPILATTION_DATABASE = "CompilationDatabase"; //$NON-NLS-1$
5656
private static final String SET_COMPILATION_DB = COMPILE_FLAGS + ": {" + COMPILATTION_DATABASE + ": %s}"; //$NON-NLS-1$ //$NON-NLS-2$
@@ -130,7 +130,7 @@ private String getRelativeDatabasePath(IProject project, ICProjectDescription ne
130130
* @throws CoreException
131131
*/
132132
@SuppressWarnings("unchecked")
133-
private void setCompilationDatabase(IProject project, String databasePath) {
133+
public void setCompilationDatabase(IProject project, String databasePath) {
134134
var configFile = project.getFile(CLANGD_CONFIG_FILE_NAME);
135135
try {
136136
if (createClangdConfigFile(configFile, project.getDefaultCharset(), databasePath, false)) {
Lines changed: 60 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package org.eclipse.cdt.lsp.clangd.tests;
1616

17+
import static org.junit.jupiter.api.Assertions.assertThrows;
1718
import static org.junit.jupiter.api.Assertions.assertTrue;
1819
import static org.mockito.Mockito.mock;
1920
import static org.mockito.Mockito.when;
@@ -32,6 +33,7 @@
3233
import org.eclipse.cdt.core.settings.model.ICProjectDescription;
3334
import org.eclipse.cdt.internal.core.settings.model.CConfigurationDescriptionCache;
3435
import org.eclipse.cdt.lsp.clangd.ClangdCProjectDescriptionListener;
36+
import org.eclipse.cdt.lsp.clangd.ClangdConfigurationFileManager;
3537
import org.eclipse.cdt.lsp.clangd.MacroResolver;
3638
import org.eclipse.core.resources.IFile;
3739
import org.eclipse.core.resources.IProject;
@@ -46,11 +48,12 @@
4648
import org.junit.jupiter.api.Test;
4749
import org.junit.jupiter.api.TestInfo;
4850
import org.junit.jupiter.api.io.TempDir;
51+
import org.yaml.snakeyaml.scanner.ScannerException;
4952

50-
final class ClangdConfigurationManagerTest {
53+
final class ClangdConfigurationFileManagerTest {
5154

52-
private static final String RELATIVE_DIR_PATH_BUILD_DEFAULT = "build/default";
53-
private static final String RELATIVE_DIR_PATH_BUILD_DEBUG = "build/debug";
55+
private static final String RELATIVE_DIR_PATH_BUILD_DEFAULT = "build" + File.separator + "default";
56+
private static final String RELATIVE_DIR_PATH_BUILD_DEBUG = "build" + File.separator + "debug";
5457
private static final String EXPANDED_CDB_SETTING = "CompileFlags: {Add: -ferror-limit=500, CompilationDatabase: %s, Compiler: g++}\nDiagnostics:\n ClangTidy: {Add: modernize*, Remove: modernize-use-trailing-return-type}\n";
5558
private static final String DEFAULT_CDB_SETTING = "CompileFlags: {CompilationDatabase: %s}";
5659
private static final String MODIFIED_DEFAULT_CDB_SETTING = DEFAULT_CDB_SETTING + "\n";
@@ -82,8 +85,6 @@ public void setUp(TestInfo testInfo) throws CoreException {
8285
project = TestUtils.createCProject(projectName);
8386
TestUtils.setLspPreferred(project, true);
8487
when(event.getProject()).thenReturn(project);
85-
cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEFAULT).toPortableString());
86-
when(setting.getBuilderCWD()).thenReturn(cwdBuilder);
8788
}
8889

8990
@AfterEach
@@ -92,14 +93,28 @@ public void cleanUp() throws CoreException {
9293
}
9394

9495
private static File createFile(File parent, String format, String cdbDirectoryPath) throws FileNotFoundException {
95-
var file = new File(parent, ClangdCProjectDescriptionListener.CLANGD_CONFIG_FILE_NAME);
96+
return createFile(parent, ClangdCProjectDescriptionListener.CLANGD_CONFIG_FILE_NAME, format, cdbDirectoryPath);
97+
}
98+
99+
private static File createFile(File parent, String fileName, String format, String cdbDirectoryPath)
100+
throws FileNotFoundException {
101+
var file = new File(parent, fileName);
96102
try (var writer = new PrintWriter(file)) {
97103
writer.printf(format, cdbDirectoryPath);
98104
}
99105
return file;
100106
}
101107

102-
private IFile createFile(String format, String cdbDirectoryPath)
108+
/**
109+
* Creates a .clangd file in the current project
110+
* @param format
111+
* @param cdbDirectoryPath
112+
* @return
113+
* @throws UnsupportedEncodingException
114+
* @throws IOException
115+
* @throws CoreException
116+
*/
117+
private IFile createConfigFile(String format, String cdbDirectoryPath)
103118
throws UnsupportedEncodingException, IOException, CoreException {
104119
var file = project.getFile(ClangdCProjectDescriptionListener.CLANGD_CONFIG_FILE_NAME);
105120
try (final var data = new ByteArrayInputStream(
@@ -126,11 +141,12 @@ void testCreateClangdConfigFileInProject() throws IOException, CoreException {
126141
var configFile = new File(projectDir, ClangdCProjectDescriptionListener.CLANGD_CONFIG_FILE_NAME);
127142
var refFile = createFile(TEMP_DIR, DEFAULT_CDB_SETTING, RELATIVE_DIR_PATH_BUILD_DEFAULT);
128143
// The current working directory of the builder in the project is set to RELATIVE_DIR_PATH_BUILD_DEFAULT:
129-
//cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEFAULT).toPortableString());
144+
cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEFAULT).toPortableString());
145+
when(setting.getBuilderCWD()).thenReturn(cwdBuilder);
130146

131147
// GIVEN a project without .clangd project configuration file:
132148
assertTrue(configFile.length() == 0);
133-
// WHEN the ClangdConfigurationManager.setCompilationDatabase method gets called:
149+
// WHEN the ClangdConfigurationManager.handleEvent method gets called:
134150
clangdConfigurationManager.handleEvent(event, macroResolver);
135151
// THEN a new file has been created in the project:
136152
assertTrue(configFile.length() > 0);
@@ -151,12 +167,13 @@ void testCreateClangdConfigFileInProject() throws IOException, CoreException {
151167
void testEmptyClangdConfigFileInProject() throws IOException, CoreException {
152168
var refFile = createFile(TEMP_DIR, DEFAULT_CDB_SETTING, RELATIVE_DIR_PATH_BUILD_DEFAULT);
153169
// The current working directory of the builder in the project is set to RELATIVE_DIR_PATH_BUILD_DEFAULT:
154-
//cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEFAULT).toPortableString());
170+
cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEFAULT).toPortableString());
171+
when(setting.getBuilderCWD()).thenReturn(cwdBuilder);
155172

156173
// GIVEN an existing but empty .clangd configuration file in the project:
157-
var emptyConfigFile = createFile("%s", " ");
158-
// WHEN the ClangdConfigurationManager.setCompilationDatabase method gets called with a new cdb path "build/debug":
159-
//clangdConfigurationManager.handleEvent(event, macroResolver);
174+
var emptyConfigFile = createConfigFile("%s", " ");
175+
// WHEN the ClangdConfigurationManager.handleEvent method gets called with a new cdb path "build/debug":
176+
clangdConfigurationManager.handleEvent(event, macroResolver);
160177
// THEN the updated file matches the expected content with the given CompilationDatabase directory "build/debug":
161178
assertTrue(Arrays.equals(Files.readAllBytes(emptyConfigFile.getLocation().toFile().toPath()),
162179
Files.readAllBytes(refFile.toPath())));
@@ -175,29 +192,35 @@ void testEmptyClangdConfigFileInProject() throws IOException, CoreException {
175192
void testUpdateClangdConfigFileInProject() throws IOException, CoreException {
176193
var projectDir = project.getLocation().toPortableString();
177194
var configFile = new File(projectDir, ClangdCProjectDescriptionListener.CLANGD_CONFIG_FILE_NAME);
178-
var cwdDefault = createFile(TEMP_DIR, MODIFIED_DEFAULT_CDB_SETTING, RELATIVE_DIR_PATH_BUILD_DEFAULT);
179-
var cwdDebug = createFile(TEMP_DIR, MODIFIED_DEFAULT_CDB_SETTING, RELATIVE_DIR_PATH_BUILD_DEBUG);
195+
var refFileDefault = createFile(TEMP_DIR, ".clangdDefault", DEFAULT_CDB_SETTING,
196+
RELATIVE_DIR_PATH_BUILD_DEFAULT);
197+
// Use MODIFIED_DEFAULT_CDB_SETTING here, because the org.yaml.snakeyaml.Yaml.dump appends a '\n' at the last line:
198+
var refFileDebug = createFile(TEMP_DIR, ".clangdDebug", MODIFIED_DEFAULT_CDB_SETTING,
199+
RELATIVE_DIR_PATH_BUILD_DEBUG);
180200
// The current working directory of the builder in the project is set to RELATIVE_DIR_PATH_BUILD_DEFAULT:
181-
//cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEFAULT).toPortableString());
201+
cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEFAULT).toPortableString());
202+
when(setting.getBuilderCWD()).thenReturn(cwdBuilder);
182203

183204
// GIVEN a project without .clangd project configuration file:
184205
assertTrue(configFile.length() == 0);
185206
// AND the ClangdConfigurationManager.handleEvent method gets called:
186207
clangdConfigurationManager.handleEvent(event, macroResolver);
187208
// THEN a new file has been created in the project:
188209
assertTrue(configFile.length() > 0);
189-
// THEN the file matches the expected content:
190-
//assertTrue(Arrays.equals(Files.readAllBytes(configFile.toPath()), Files.readAllBytes(cwdDefault.toPath())));
191-
// WHEN the active build configuration changes and the CWD is set to RELATIVE_DIR_PATH_BUILD_DEBUG:
192-
//cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEBUG).toPortableString());
210+
// THEN the created file matches the expected content:
211+
assertTrue(Arrays.equals(Files.readAllBytes(configFile.toPath()), Files.readAllBytes(refFileDefault.toPath())));
212+
213+
// WHEN the CWD in the build configuration changes to build/debug:
214+
cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEBUG).toPortableString());
215+
when(setting.getBuilderCWD()).thenReturn(cwdBuilder);
193216
// AND the handleEvent gets called again:
194217
clangdConfigurationManager.handleEvent(event, macroResolver);
195218
// THEN the updated file matches the expected content:
196-
assertTrue(Arrays.equals(Files.readAllBytes(configFile.toPath()), Files.readAllBytes(cwdDebug.toPath())));
219+
assertTrue(Arrays.equals(Files.readAllBytes(configFile.toPath()), Files.readAllBytes(refFileDebug.toPath())));
197220

198221
//clean up:
199-
cwdDefault.delete();
200-
cwdDebug.delete();
222+
refFileDefault.delete();
223+
refFileDebug.delete();
201224
}
202225

203226
/**
@@ -211,9 +234,10 @@ void testUpdateExpandedClangdConfigFileInProject() throws IOException, CoreExcep
211234
var refFile = createFile(TEMP_DIR, EXPANDED_CDB_SETTING, RELATIVE_DIR_PATH_BUILD_DEBUG);
212235

213236
// GIVEN an existing expanded .clangd configuration file in the project pointing to "build/default":
214-
var configFile = createFile(EXPANDED_CDB_SETTING, RELATIVE_DIR_PATH_BUILD_DEFAULT);
237+
var configFile = createConfigFile(EXPANDED_CDB_SETTING, RELATIVE_DIR_PATH_BUILD_DEFAULT);
215238
// WHEN the ClangdConfigurationManager.handleEvent method gets called and the builder CWD points to "build/debug":
216-
//cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEBUG).toPortableString());
239+
cwdBuilder = new Path(project.getLocation().append(RELATIVE_DIR_PATH_BUILD_DEBUG).toPortableString());
240+
when(setting.getBuilderCWD()).thenReturn(cwdBuilder);
217241
clangdConfigurationManager.handleEvent(event, macroResolver);
218242
// THEN the updated file matches the expected content:
219243
assertTrue(Arrays.equals(Files.readAllBytes(configFile.getLocation().toFile().toPath()),
@@ -229,15 +253,16 @@ void testUpdateExpandedClangdConfigFileInProject() throws IOException, CoreExcep
229253
* @throws IOException
230254
* @throws CoreException
231255
*/
232-
// @Test
233-
// void testInvalidYamlSyntax() throws IOException, CoreException {
234-
// // GIVEN an existing .clangd configuration file with invalid yaml syntax (contains tab):
235-
// createFile(INVALID_YAML_SYNTAX_CONTAINS_TAB, RELATIVE_DIR_PATH_BUILD_DEFAULT);
236-
// // WHEN the ClangdConfigurationManager.setCompilationDatabase method gets called with a new cdb path "build/debug":
237-
// // THEN a ScannerExcpetion is expected:
238-
// assertThrows(ScannerException.class, () -> {
239-
// clangdConfigurationManager.handleEvent(event, macroResolver);//RELATIVE_DIR_PATH_BUILD_DEBUG);
240-
// });
241-
// }
256+
@Test
257+
void testInvalidYamlSyntax() throws IOException, CoreException {
258+
// GIVEN an existing .clangd configuration file with invalid yaml syntax (contains tab):
259+
createConfigFile(INVALID_YAML_SYNTAX_CONTAINS_TAB, RELATIVE_DIR_PATH_BUILD_DEFAULT);
260+
// WHEN the ClangdConfigurationManager.setCompilationDatabasePath method gets called with a new cdb path "build/debug":
261+
// THEN a ScannerExcpetion is expected:
262+
assertThrows(ScannerException.class, () -> {
263+
((ClangdConfigurationFileManager) clangdConfigurationManager).setCompilationDatabase(project,
264+
RELATIVE_DIR_PATH_BUILD_DEBUG);
265+
});
266+
}
242267

243268
}

0 commit comments

Comments
 (0)