Skip to content

Commit b4f87cf

Browse files
committed
[#26] add missing contentTypeBindings
The org.eclipse.tm4e.language_pack plug-in adds content types for C/C++ files. These content types needs to be considered during filtering This is a fix for eclipse-tm4e/tm4e#499
1 parent 1f3aa8c commit b4f87cf

File tree

6 files changed

+210
-25
lines changed

6 files changed

+210
-25
lines changed

bundles/org.eclipse.cdt.lsp.editor.ui.test/src/org/eclipse/cdt/lsp/editor/ui/test/preference/LspEditorPreferencesTesterTest.java

Lines changed: 129 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import java.io.File;
77
import java.io.IOException;
88
import java.io.UnsupportedEncodingException;
9+
import java.nio.file.Files;
10+
911
import org.eclipse.cdt.lsp.LspPlugin;
1012
import org.eclipse.cdt.lsp.editor.ui.test.TestUtils;
1113
import org.eclipse.cdt.lsp.server.ICLanguageServerProvider;
@@ -15,18 +17,24 @@
1517
import org.junit.jupiter.api.BeforeEach;
1618
import org.junit.jupiter.api.Test;
1719
import org.junit.jupiter.api.TestInfo;
18-
import org.junit.jupiter.api.io.TempDir;
1920

2021

2122
public class LspEditorPreferencesTesterTest {
2223
private static final String FILE_CONTENT = "// sample file content";
2324
private static final String MAIN_CPP = "main.cpp";
24-
private static final String EXTERNAL_HEADER_HPP = "ExternalHeader.hpp";
25+
private static final String HEADER_HPP = "header.hpp";
26+
private static final String MAIN_C = "main.c";
27+
private static final String HEADER_H = "header.h";
28+
//private static final String EXTERNAL_HEADER_HPP = "ExternalHeader.hpp";
2529
private IProject project;
2630

27-
@TempDir
28-
private File tempDir;
31+
// @TempDir -> does not work with org.junit.jupiter.api. Needs junit-jupiter-api and junit-jupiter-params.
32+
// These packages are not accessible on the CI build server because we build with Eclipse 2022-06
33+
// Path tempDir = Files.createTempFile("ExternalHeader", ".hpp", null);
2934

35+
private File createTempHppHeaderfile() throws IOException {
36+
return Files.createTempFile("ExternalHeader", ".hpp").toFile();
37+
}
3038

3139
@BeforeEach
3240
public void setUp(TestInfo testInfo) throws CoreException {
@@ -81,11 +89,11 @@ public void testLsEnableByUriTest_WITHOUT_LsEditorPreferred() throws CoreExcepti
8189
}
8290

8391
/**
84-
* Tests whether the C/C++ Editor is used for a resource to open whose project has "Prefer C/C++ Editor (LSP)" disabled.
92+
* Tests whether the C/C++ Editor is used for a C++ source file to open whose project has "Prefer C/C++ Editor (LSP)" disabled.
8593
* @throws UnsupportedEncodingException
8694
*/
8795
@Test
88-
public void testEditorUsedToOpenFile_WITHOUT_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
96+
public void testEditorUsedToOpenCppFile_WITHOUT_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
8997
//GIVEN is a project with DISABLED "Prefer C/C++ Editor (LSP)" in the preferences:
9098
TestUtils.setLspPreferred(project, false);
9199
//AND a file exits in the given project:
@@ -94,14 +102,15 @@ public void testEditorUsedToOpenFile_WITHOUT_LsEditorPreferred() throws CoreExce
94102
var editorPart = TestUtils.openInEditor(file);
95103
//THEN it will be opened in the C/C++ Editor:
96104
assertEquals(LspPlugin.C_EDITOR_ID, editorPart.getEditorSite().getId());
105+
TestUtils.closeEditor(editorPart, false);
97106
}
98107

99108
/**
100-
* Tests whether the C/C++ Editor (LSP) is used for a resource to open whose project has "Prefer C/C++ Editor (LSP)" enabled.
109+
* Tests whether the C/C++ Editor (LSP) is used for a C++ source file to open whose project has "Prefer C/C++ Editor (LSP)" enabled.
101110
* @throws UnsupportedEncodingException
102111
*/
103112
@Test
104-
public void testEditorUsedToOpenFile_WITH_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
113+
public void testEditorUsedToOpenCppFile_WITH_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
105114
//GIVEN is a project with ENABLED "Prefer C/C++ Editor (LSP)" in the preferences:
106115
TestUtils.setLspPreferred(project, true);
107116
//AND a file exits in the given project:
@@ -110,6 +119,109 @@ public void testEditorUsedToOpenFile_WITH_LsEditorPreferred() throws CoreExcepti
110119
var editorPart = TestUtils.openInEditor(file);
111120
//THEN it will be opened in the C/C++ Editor (LSP):
112121
assertEquals(LspPlugin.LSP_C_EDITOR_ID, editorPart.getEditorSite().getId());
122+
TestUtils.closeEditor(editorPart, false);
123+
}
124+
125+
/**
126+
* Tests whether the C/C++ Editor is used for a C++ header file to open whose project has "Prefer C/C++ Editor (LSP)" disabled.
127+
* @throws UnsupportedEncodingException
128+
*/
129+
@Test
130+
public void testEditorUsedToOpenCppHeaderFile_WITHOUT_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
131+
//GIVEN is a project with DISABLED "Prefer C/C++ Editor (LSP)" in the preferences:
132+
TestUtils.setLspPreferred(project, false);
133+
//AND a file exits in the given project:
134+
var file = TestUtils.createFile(project, HEADER_HPP, FILE_CONTENT);
135+
//WHEN this file will be opened:
136+
var editorPart = TestUtils.openInEditor(file);
137+
//THEN it will be opened in the C/C++ Editor:
138+
assertEquals(LspPlugin.C_EDITOR_ID, editorPart.getEditorSite().getId());
139+
TestUtils.closeEditor(editorPart, false);
140+
}
141+
142+
/**
143+
* Tests whether the C/C++ Editor (LSP) is used for a C++ header file to open whose project has "Prefer C/C++ Editor (LSP)" enabled.
144+
* @throws UnsupportedEncodingException
145+
*/
146+
@Test
147+
public void testEditorUsedToOpenCppHeaderFile_WITH_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
148+
//GIVEN is a project with ENABLED "Prefer C/C++ Editor (LSP)" in the preferences:
149+
TestUtils.setLspPreferred(project, true);
150+
//AND a file exits in the given project:
151+
var file = TestUtils.createFile(project, HEADER_HPP, FILE_CONTENT);
152+
//WHEN this file will be opened:
153+
var editorPart = TestUtils.openInEditor(file);
154+
//THEN it will be opened in the C/C++ Editor (LSP):
155+
assertEquals(LspPlugin.LSP_C_EDITOR_ID, editorPart.getEditorSite().getId());
156+
TestUtils.closeEditor(editorPart, false);
157+
}
158+
159+
/**
160+
* Tests whether the C/C++ Editor is used for a C source file to open whose project has "Prefer C/C++ Editor (LSP)" disabled.
161+
* @throws UnsupportedEncodingException
162+
*/
163+
@Test
164+
public void testEditorUsedToOpenCFile_WITHOUT_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
165+
//GIVEN is a project with DISABLED "Prefer C/C++ Editor (LSP)" in the preferences:
166+
TestUtils.setLspPreferred(project, false);
167+
//AND a file exits in the given project:
168+
var file = TestUtils.createFile(project, MAIN_C, FILE_CONTENT);
169+
//WHEN this file will be opened:
170+
var editorPart = TestUtils.openInEditor(file);
171+
//THEN it will be opened in the C/C++ Editor:
172+
assertEquals(LspPlugin.C_EDITOR_ID, editorPart.getEditorSite().getId());
173+
TestUtils.closeEditor(editorPart, false);
174+
}
175+
176+
/**
177+
* Tests whether the C/C++ Editor (LSP) is used for a C source file to open whose project has "Prefer C/C++ Editor (LSP)" enabled.
178+
* @throws UnsupportedEncodingException
179+
*/
180+
@Test
181+
public void testEditorUsedToOpenCFile_WITH_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
182+
//GIVEN is a project with ENABLED "Prefer C/C++ Editor (LSP)" in the preferences:
183+
TestUtils.setLspPreferred(project, true);
184+
//AND a file exits in the given project:
185+
var file = TestUtils.createFile(project, MAIN_C, FILE_CONTENT);
186+
//WHEN this file will be opened:
187+
var editorPart = TestUtils.openInEditor(file);
188+
//THEN it will be opened in the C/C++ Editor (LSP):
189+
assertEquals(LspPlugin.LSP_C_EDITOR_ID, editorPart.getEditorSite().getId());
190+
TestUtils.closeEditor(editorPart, false);
191+
}
192+
193+
/**
194+
* Tests whether the C/C++ Editor is used for a C header file to open whose project has "Prefer C/C++ Editor (LSP)" disabled.
195+
* @throws UnsupportedEncodingException
196+
*/
197+
@Test
198+
public void testEditorUsedToOpenCHeaderFile_WITHOUT_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
199+
//GIVEN is a project with DISABLED "Prefer C/C++ Editor (LSP)" in the preferences:
200+
TestUtils.setLspPreferred(project, false);
201+
//AND a file exits in the given project:
202+
var file = TestUtils.createFile(project, HEADER_HPP, FILE_CONTENT);
203+
//WHEN this file will be opened:
204+
var editorPart = TestUtils.openInEditor(file);
205+
//THEN it will be opened in the C/C++ Editor:
206+
assertEquals(LspPlugin.C_EDITOR_ID, editorPart.getEditorSite().getId());
207+
TestUtils.closeEditor(editorPart, false);
208+
}
209+
210+
/**
211+
* Tests whether the C/C++ Editor (LSP) is used for a C header file to open whose project has "Prefer C/C++ Editor (LSP)" enabled.
212+
* @throws UnsupportedEncodingException
213+
*/
214+
@Test
215+
public void testEditorUsedToOpenCHeaderFile_WITH_LsEditorPreferred() throws CoreException, UnsupportedEncodingException {
216+
//GIVEN is a project with ENABLED "Prefer C/C++ Editor (LSP)" in the preferences:
217+
TestUtils.setLspPreferred(project, true);
218+
//AND a file exits in the given project:
219+
var file = TestUtils.createFile(project, HEADER_H, FILE_CONTENT);
220+
//WHEN this file will be opened:
221+
var editorPart = TestUtils.openInEditor(file);
222+
//THEN it will be opened in the C/C++ Editor (LSP):
223+
assertEquals(LspPlugin.LSP_C_EDITOR_ID, editorPart.getEditorSite().getId());
224+
TestUtils.closeEditor(editorPart, false);
113225
}
114226

115227
/**
@@ -119,12 +231,14 @@ public void testEditorUsedToOpenFile_WITH_LsEditorPreferred() throws CoreExcepti
119231
@Test
120232
public void testLsEnableByExternalUriTest_NoEditorOpen() throws CoreException, IOException {
121233
//GIVEN is an external file which does not exists in the given project and is not opened:
122-
File externalFile = new File(tempDir, EXTERNAL_HEADER_HPP);
234+
File externalFile = createTempHppHeaderfile();
123235
//AND a ICLanguageServerProvider which uses LspEditorPreferencesTester as enabledWhen tester:
124236
ICLanguageServerProvider cLanguageServerProvider = LspPlugin.getDefault().getCLanguageServerProvider();
125237
//WHEN the LspEditorPreferencesTester gets called by the property tester in the enabledWhen element of the serverProvider extension point,
126238
//THEN the LspEditorPreferencesTester.test returns FALSE for the given file URI:
127239
assertTrue(!cLanguageServerProvider.isEnabledFor(externalFile.toURI()));
240+
//ensure clean up
241+
externalFile.delete();
128242
}
129243

130244
/**
@@ -133,7 +247,7 @@ public void testLsEnableByExternalUriTest_NoEditorOpen() throws CoreException, I
133247
@Test
134248
public void testLsEnableByExternalUriTest_OpenedInLspCEditor() throws CoreException, IOException {
135249
//GIVEN is an existing external file:
136-
File externalFile = new File(tempDir, EXTERNAL_HEADER_HPP);
250+
File externalFile = createTempHppHeaderfile();
137251
externalFile.createNewFile();
138252
//AND it's opened in the LSP based C/C++ Editor:
139253
var editor = TestUtils.openInEditor(externalFile.toURI(), LspPlugin.LSP_C_EDITOR_ID);
@@ -143,6 +257,8 @@ public void testLsEnableByExternalUriTest_OpenedInLspCEditor() throws CoreExcept
143257
//THEN the LspEditorPreferencesTester.test returns TRUE for the given file URI:
144258
assertTrue(cLanguageServerProvider.isEnabledFor(externalFile.toURI()));
145259
TestUtils.closeEditor(editor, false);
260+
//ensure clean up
261+
externalFile.delete();
146262
}
147263

148264
/**
@@ -151,7 +267,7 @@ public void testLsEnableByExternalUriTest_OpenedInLspCEditor() throws CoreExcept
151267
@Test
152268
public void testLsEnableByExternalUriTest_OpenedInCEditor() throws CoreException, IOException {
153269
//GIVEN is an existing external file:
154-
File externalFile = new File(tempDir, EXTERNAL_HEADER_HPP);
270+
File externalFile = createTempHppHeaderfile();
155271
externalFile.createNewFile();
156272
//AND it's opened in the C/C++ Editor:
157273
var editor = TestUtils.openInEditor(externalFile.toURI(), LspPlugin.C_EDITOR_ID);
@@ -161,6 +277,8 @@ public void testLsEnableByExternalUriTest_OpenedInCEditor() throws CoreException
161277
//THEN the LspEditorPreferencesTester.test returns FALSE for the given file URI:
162278
assertTrue(!cLanguageServerProvider.isEnabledFor(externalFile.toURI()));
163279
TestUtils.closeEditor(editor, false);
280+
//ensure clean up
281+
externalFile.delete();
164282
}
165283

166284
}

bundles/org.eclipse.cdt.lsp.editor.ui/src/org/eclipse/cdt/lsp/editor/ui/clangd/CompileCommandsMonitor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Set;
1919
import java.util.stream.Stream;
2020

21+
import org.eclipse.cdt.lsp.LspUtils;
2122
import org.eclipse.cdt.lsp.editor.ui.LspEditorUiPlugin;
2223
import org.eclipse.core.resources.IFile;
2324
import org.eclipse.core.resources.IProject;
@@ -71,8 +72,7 @@ private boolean isCppFile(IResource resource) {
7172
if (resource instanceof IFile) {
7273
var contentTypes = Platform.getContentTypeManager().findContentTypesFor(((IFile) resource).getName());
7374
return Arrays.stream(contentTypes).anyMatch(contentType -> {
74-
var id = contentType.getId();
75-
return id.startsWith("org.eclipse.cdt.core.c") && (id.endsWith("Source") || id.endsWith("Header"));
75+
return LspUtils.isCContentType(contentType.getId());
7676
});
7777
}
7878
return false;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package org.eclipse.cdt.lsp.test;
2+
3+
import static org.junit.jupiter.api.Assertions.*;
4+
5+
import org.eclipse.cdt.core.CCorePlugin;
6+
import org.eclipse.cdt.lsp.LspUtils;
7+
import org.junit.jupiter.api.Test;
8+
9+
class LspUtilsTest {
10+
11+
@Test
12+
void testIsCContentType_EmptyId() {
13+
assertTrue(!LspUtils.isCContentType(""));
14+
}
15+
16+
@Test
17+
void testIsCContentType_CppContentTypeFromTM4E() {
18+
assertTrue(LspUtils.isCContentType("lng.cpp"));
19+
}
20+
21+
@Test
22+
void testIsCContentType_CONTENT_TYPE_CSOURCE() {
23+
assertTrue(LspUtils.isCContentType(CCorePlugin.CONTENT_TYPE_CSOURCE));
24+
}
25+
26+
@Test
27+
void testIsCContentType_CONTENT_TYPE_CHEADER() {
28+
assertTrue(LspUtils.isCContentType(CCorePlugin.CONTENT_TYPE_CHEADER));
29+
}
30+
31+
@Test
32+
void testIsCContentType_CONTENT_TYPE_CXXSOURCE() {
33+
assertTrue(LspUtils.isCContentType(CCorePlugin.CONTENT_TYPE_CXXSOURCE));
34+
}
35+
36+
@Test
37+
void testIsCContentType_CONTENT_TYPE_CXXHEADER() {
38+
assertTrue(LspUtils.isCContentType(CCorePlugin.CONTENT_TYPE_CXXHEADER));
39+
}
40+
41+
}

bundles/org.eclipse.cdt.lsp/plugin.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,16 @@
1717
<contentTypeBinding
1818
contentTypeId="org.eclipse.cdt.core.cxxSource">
1919
</contentTypeBinding>
20+
<contentTypeBinding
21+
contentTypeId="lng.cpp"> <!-- // TODO: The content type definition from TM4E "lng.cpp" can be omitted here if either https://github.com/eclipse-cdt/cdt/pull/310 or
22+
// https://github.com/eclipse/tm4e/pull/500 has been merged. -->
23+
</contentTypeBinding>
2024
</editor>
25+
<editorContentTypeBinding
26+
contentTypeId="lng.cpp"
27+
editorId="org.eclipse.cdt.ui.editor.CEditor"> <!-- // TODO: The content type definition from TM4E "lng.cpp" can be omitted here if either https://github.com/eclipse-cdt/cdt/pull/310 or
28+
// https://github.com/eclipse/tm4e/pull/500 has been merged. -->
29+
</editorContentTypeBinding>
2130
</extension>
2231
<extension
2332
point="org.eclipse.lsp4e.languageServer">
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.eclipse.cdt.lsp;
2+
3+
public class LspUtils {
4+
5+
/**
6+
* Checks if given ContentType id matches the content types for C/C++ files.
7+
*
8+
* @param id ContentType id
9+
* @return {@code true} if C/C++ content type
10+
*/
11+
public static boolean isCContentType(String id) {
12+
// TODO: The content type definition from TM4E "lng.cpp" can be omitted if either https://github.com/eclipse-cdt/cdt/pull/310 or
13+
// https://github.com/eclipse/tm4e/pull/500 has been merged.
14+
return ( id.startsWith("org.eclipse.cdt.core.c") && (id.endsWith("Source") || id.endsWith("Header")) ) || "lng.cpp".equals(id);
15+
}
16+
17+
}

bundles/org.eclipse.cdt.lsp/src/org/eclipse/cdt/lsp/editor/CEditorAssociationOverride.java

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212

1313
package org.eclipse.cdt.lsp.editor;
1414

15-
import org.eclipse.cdt.core.CCorePlugin;
1615
import org.eclipse.cdt.lsp.LspPlugin;
16+
import org.eclipse.cdt.lsp.LspUtils;
1717
import org.eclipse.cdt.lsp.server.ICLanguageServerProvider;
1818
import org.eclipse.core.resources.IFile;
1919
import org.eclipse.core.resources.IResource;
@@ -72,12 +72,10 @@ public IEditorDescriptor overrideDefaultEditor(String fileName, IContentType con
7272
}
7373

7474
private boolean isNoCElement(IContentType contentType) {
75-
if (contentType == null || !(CCorePlugin.CONTENT_TYPE_CHEADER.equals(contentType.getId()) ||
76-
CCorePlugin.CONTENT_TYPE_CSOURCE.equals(contentType.getId()) ||
77-
CCorePlugin.CONTENT_TYPE_CXXHEADER.equals(contentType.getId()) ||
78-
CCorePlugin.CONTENT_TYPE_CXXSOURCE.equals(contentType.getId())))
75+
if (contentType == null) {
7976
return true;
80-
return false;
77+
}
78+
return !LspUtils.isCContentType(contentType.getId());
8179
}
8280

8381
private IEditorDescriptor[] editorFilter(String editorId, IEditorDescriptor[] editorDescriptors) {
@@ -100,15 +98,17 @@ private IEditorDescriptor getEditorDescriptor(IEditorInput editorInput, IContent
10098
return null;
10199

102100
if (cLanguageServerProvider.isEnabledFor(editorInput)) {
103-
return getLspCEditor(editorInput, contentType);
104-
}
105-
return null;
101+
return getEditorDescriptorById(editorInput.getName(), LspPlugin.LSP_C_EDITOR_ID, contentType); // return LSP based C/C++ Editor
102+
}
103+
// TODO: return null; when either https://github.com/eclipse-cdt/cdt/pull/310 or
104+
// https://github.com/eclipse/tm4e/pull/500 has been merged.
105+
return getEditorDescriptorById(editorInput.getName(), LspPlugin.C_EDITOR_ID, contentType); // return C/C++ Editor
106106
}
107107

108-
private IEditorDescriptor getLspCEditor(IEditorInput editorInput, IContentType contentType) {
108+
private IEditorDescriptor getEditorDescriptorById(String fileName, String editorId, IContentType contentType) {
109109
IEditorRegistry registry = PlatformUI.getWorkbench().getEditorRegistry();
110-
for (IEditorDescriptor descriptor : registry.getEditors(editorInput.getName(), contentType)) {
111-
if (LspPlugin.LSP_C_EDITOR_ID.equals(descriptor.getId())) {
110+
for (IEditorDescriptor descriptor : registry.getEditors(fileName, contentType)) {
111+
if (editorId.equals(descriptor.getId())) {
112112
return descriptor;
113113
}
114114
}

0 commit comments

Comments
 (0)