8000 [#47] Add action to switch between Source/Header by ddscharfe · Pull Request #48 · eclipse-cdt/cdt-lsp · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

[#47] Add action to switch between Source/Header #48

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ Bundle-Vendor: Eclipse.org
Fragment-Host: org.eclipse.cdt.lsp.editor.ui;bundle-version="0.0.0"
Require-Bundle: org.eclipse.cdt.lsp,
junit-jupiter-api,
org.yaml.snakeyaml
org.yaml.snakeyaml,
org.objenesis,
net.bytebuddy.byte-buddy,
net.bytebuddy.byte-buddy-agent,
org.mockito
Automatic-Module-Name: org.eclipse.cdt.lsp.editor.ui.test
Bundle-RequiredExecutionEnvironment: JavaSE-17
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*******************************************************************************
* Copyright (c) 2023 COSEDA Technologies GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dominic Scharfe (COSEDA Technologies GmbH) - initial implementation
*******************************************************************************/
package org.eclipse.cdt.lsp.editor.ui.test.commands;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import org.eclipse.cdt.lsp.LspPlugin;
import org.eclipse.cdt.lsp.editor.ui.commands.LspEditorActiveTester;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.texteditor.ITextEditor;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class LspEditorActiveTesterTest {

LspEditorActiveTester tut;

IEditorPart editorPart;
IEditorSite editorSite;

@BeforeEach
public void setup() {
tut = new LspEditorActiveTester();

editorPart = mock(IEditorPart.class);
editorSite = mock(IEditorSite.class);

when(editorPart.getSite()).thenReturn(editorSite);
}

/**
* Assert that a receiver which is not an editor part is not detected as c
* editor.
*/
@Test
public void nonEditorPart() {
assertFalse(tut.test(new String("not an edit part"), LspEditorActiveTester.IS_LSP_CEDITOR_PROPERTY, null, tut));
}

/**
* Assert that tester only tests for the correct property, even if the given
* receiver is an {@link IEditorPart}.
*/
@Test
public void editorPartNonMatchingProperty() {
assertFalse(tut.test(editorPart, "someOtherProperty", null, tut));
}

/**
* Assert that an {@link IEditorPart} with some other id is not detected as c editor.
*/
@Test
public void matchingEditorPartWithNonMatchingId() {
when(editorSite.getId()).thenReturn("someId");
assertTestResult(false);
}

/**
* Assert that an {@link IEditorPart} with the c editor id is detected as c editor.
*/
@Test
public void matchingEditorPartWithMatchingId() {
when(editorSite.getId()).thenReturn(LspPlugin.LSP_C_EDITOR_ID);
assertTestResult(true);
}

/**
* Assert that an {@link IEditorPart} with an "inner editor" (part adapts to
* {@link ITextEditor.class}) is not detected as c editor when the inner editor
* doesn't have the c editor id.
*/
@Test
public void editorPartWithInnerNonMatchingEditor() {
ITextEditor innerEditor = mock(ITextEditor.class);
IEditorSite innerEditorSite = mock(IEditorSite.class);
when(innerEditor.getSite()).thenReturn(innerEditorSite);
when(innerEditorSite.getId()).thenReturn("someId");
when(editorPart.getAdapter(ITextEditor.class)).thenReturn(innerEditor);
when(editorSite.getId()).thenReturn("someOtherId");

assertTestResult(false);
}

/**
* Assert that an {@link IEditorPart} with an "inner editor" (part adapts to
* {@link ITextEditor.class}) is detected as c editor when the inner editor
* has the c editor id.
*/
@Test
public void editorPartWithInnerMatchingEditor() {
ITextEditor innerEditor = mock(ITextEditor.class);
IEditorSite innerEditorSite = mock(IEditorSite.class);
when(innerEditor.getSite()).thenReturn(innerEditorSite);
when(innerEditorSite.getId()).thenReturn(LspPlugin.LSP_C_EDITOR_ID);
when(editorPart.getAdapter(ITextEditor.class)).thenReturn(innerEditor);
when(editorSite.getId()).thenReturn("someOtherId");

assertTestResult(true);
}

/**
* Helper method.
*/
private void assertTestResult(boolean expectedResult) {
assertEquals(expectedResult, tut.test(editorPart, LspEditorActiveTester.IS_LSP_CEDITOR_PROPERTY, null, tut));
}

}
6 changes: 5 additions & 1 deletion bundles/org.eclipse.cdt.lsp.editor.ui/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ Bundle-SymbolicName: org.eclipse.cdt.lsp.editor.ui;singleton:=true
Bundle-Version: 1.0.0.qualifier
Bundle-Activator: org.eclipse.cdt.lsp.editor.ui.LspEditorUiPlugin
Bundle-Vendor: Eclipse.org
Bundle-Localization: plugin
Require-Bundle: org.eclipse.ui,
org.eclipse.core.runtime,
org.eclipse.cdt.lsp,
Expand All @@ -15,7 +16,10 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.ui.editors,
org.eclipse.cdt.core,
org.eclipse.jface.text,
org.yaml.snakeyaml
org.yaml.snakeyaml,
org.eclipse.lsp4j,
org.eclipse.lsp4e,
org.eclipse.lsp4j.jsonrpc
Bundle-RequiredExecutionEnvironment: JavaSE-17
Automatic-Module-Name: org.eclipse.cdt.lsp.editor.ui
Bundle-ActivationPolicy: lazy
3 changes: 2 additions & 1 deletion bundles/org.eclipse.cdt.lsp.editor.ui/build.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ source.. = src/
output.. = bin/
bin.includes = META-INF/,\
.,\
plugin.xml
plugin.xml,\
plugin.properties
2 changes: 2 additions & 0 deletions bundles/org.eclipse.cdt.lsp.editor.ui/plugin.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Commands.ToggleSourceAndHeader.name=Toggle Source/Header
PopupMenu.ToggleSourceAndHeader.label=Toggle Source/Header
53 changes: 53 additions & 0 deletions bundles/org.eclipse.cdt.lsp.editor.ui/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@
properties="LspEditorPreference"
type="java.lang.Object">
</propertyTester>
<propertyTester
class="org.eclipse.cdt.lsp.editor.ui.commands.LspEditorActiveTester"
id="org.eclipse.cdt.lsp.editor.ui.isLspCEditor"
namespace="org.eclipse.cdt.lsp.editor.ui"
properties="isLspCEditor"
type="java.lang.Object">
</propertyTester>
</extension>
<extension
point="org.eclipse.cdt.lsp.serverProvider">
Expand All @@ -52,4 +59,50 @@
</server>
</extension>

<extension
point="org.eclipse.ui.commands">
<command
id="org.eclipse.cdt.lsp.editor.ui.toggle_source_and_header"
name="%Commands.ToggleSourceAndHeader.name">
</command>
</extension>
<extension
point="org.eclipse.ui.bindings">
<key
commandId="org.eclipse.cdt.lsp.editor.ui.toggle_source_and_header"
contextId="org.eclipse.ui.genericeditor.genericEditorContext"
schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
sequence="M1+TAB">
</key>
</extension>
<extension
point="org.eclipse.ui.handlers">
<handler
class="org.eclipse.cdt.lsp.editor.ui.commands.ToggleSourceAndHeaderCommandHandler"
commandId="org.eclipse.cdt.lsp.editor.ui.toggle_source_and_header">
<activeWhen>
<with variable="activeEditor">
<test
property="org.eclipse.cdt.lsp.editor.ui.isLspCEditor">
</test>
</with>
</activeWhen>
</handler>
</extension>
<extension
point="org.eclipse.ui.menus">
<menuContribution
allPopups="false"
locationURI="popup:org.eclipse.ui.popup.any?before=org.eclipse.lsp4e.openCallHierarchy">
<command
commandId="org.eclipse.cdt.lsp.editor.ui.toggle_source_and_header"
label="%PopupMenu.ToggleSourceAndHeader.label"
style="push">
<visibleWhen
checkEnabled="true">
</visibleWhen>
</command>
</menuContribution>
</extension>

</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*******************************************************************************
* Copyright (c) 2023 COSEDA Technologies GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dominic Scharfe (COSEDA Technologies GmbH) - initial implementation
*******************************************************************************/
package org.eclipse.cdt.lsp.editor.ui.commands;

import java.util.Optional;

import org.eclipse.cdt.lsp.LspPlugin;
import org.eclipse.core.expressions.PropertyTester;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.ITextEditor;

/**
* Property tester for checking if a receiver is a c editor. Will evaluate
* {@code true} if the receiver can adapt to {@link ITextEditor} and has the c
* editor id.
*/
public class LspEditorActiveTester extends PropertyTester {
public final static String IS_LSP_CEDITOR_PROPERTY = "isLspCEditor";

@Override
public boolean test(Object receiver, String property, Object[] args, Object expectedValue) {
if (receiver instanceof IEditorPart && IS_LSP_CEDITOR_PROPERTY.equals(property)) {
IEditorPart innerEditor = Optional.ofNullable((IEditorPart) Adapters.adapt(receiver, ITextEditor.class))
.orElse((IEditorPart) receiver);

return LspPlugin.LSP_C_EDITOR_ID.equals(innerEditor.getSite().getId());
}
return false;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*******************************************************************************
* Copyright (c) 2023 COSEDA Technologies GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Dominic Scharfe (COSEDA Technologies GmbH) - initial implementation
*******************************************************************************/
package org.eclipse.cdt.lsp.editor.ui.commands;

import java.net.URI;
import java.util.Optional;

import org.eclipse.cdt.lsp.LspPlugin;
import org.eclipse.cdt.lsp.editor.ui.LspEditorUiPlugin;
import org.eclipse.cdt.lsp.services.ClangdLanguageServer;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.jface.text.IDocument;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.handlers.HandlerUtil;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.texteditor.ITextEditor;

public class ToggleSourceAndHeaderCommandHandler extends AbstractHandler implements IHandler {
@Override
public Object execute(ExecutionEvent event) throws ExecutionException {
return execute(HandlerUtil.getActiveEditor(event));
}

@SuppressWarnings("restriction")
private Object execute(IEditorPart activeEditor) {
// Try to adapt to ITextEditor (e.g. to support editors embedded in
// MultiPageEditorParts), otherwise use activeEditor.
IEditorPart innerEditor = Optional.ofNullable((IEditorPart) Adapters.adapt(activeEditor, ITextEditor.class))
.orElse(activeEditor);

getUri(innerEditor).ifPresent(fileUri -> {
IDocument document = org.eclipse.lsp4e.LSPEclipseUtils.getDocument(innerEditor.getEditorInput());
org.eclipse.lsp4e.LanguageServers.forDocument(document)
.computeFirst(
server -> server instanceof ClangdLanguageServer
? ((ClangdLanguageServer) server)
.switchSourceHeader(new TextDocumentIdentifier(fileUri.toString()))
: null)
.thenAccept(otherFileUri -> otherFileUri
.ifPresent(uri -> openEditor(innerEditor.getEditorSite().getPage(), URI.create(uri))));
});

return null;
}

/**
* Returns the URI of the given editor depending on the type of its
* {@link IEditorPart#getEditorInput()}.
*
* @return the URI or an empty {@link Optional} if the URI couldn't be
* determined.
*/
private static Optional<URI> getUri(IEditorPart editor) {
IEditorInput editorInput = editor.getEditorInput();

if (editorInput instanceof IFileEditorInput) {
return Optional.of(((IFileEditorInput) editor.getEditorInput()).getFile().getLocationURI());
} else if (editorInput instanceof IURIEditorInput) {
return Optional.of(((IURIEditorInput) editorInput).getURI());
} else {
return Optional.empty();
}
}

private static void openEditor(IWorkbenchPage page, URI fileUri) {
page.getWorkbenchWindow().getShell().getDisplay().asyncExec(() -> {
try {
IDE.openEditor(page, fileUri, LspPlugin.LSP_C_EDITOR_ID, true);
} catch (PartInitException e) {
StatusManager.getManager().handle(e, LspEditorUiPlugin.PLUGIN_ID);
}
});
}

}
7 changes: 5 additions & 2 deletions bundles/org.eclipse.cdt.lsp/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Bundle-Name: Language Server based C/C++ Editor
Bundle-SymbolicName: org.eclipse.cdt.lsp;singleton:=true
Bundle-Version: 1.0.0.qualifier
Export-Package: org.eclipse.cdt.lsp,
org.eclipse.cdt.lsp.server
org.eclipse.cdt.lsp.server,
org.eclipse.cdt.lsp.services
Bundle-Activator: org.eclipse.cdt.lsp.LspPlugin
Bundle-Vendor: Eclipse.org
Require-Bundle: org.eclipse.ui,
Expand All @@ -22,7 +23,9 @@ Require-Bundle: org.eclipse.ui,
org.eclipse.ui.workbench,
org.eclipse.core.expressions,
org.eclipse.jface.text,
org.eclipse.debug.ui
org.eclipse.debug.ui,
org.eclipse.lsp4j,
org.eclipse.lsp4j.jsonrpc
Bundle-RequiredExecutionEnvironment: JavaSE-17
Automatic-Module-Name: org.eclipse.cdt.lsp
9A2F Bundle-ActivationPolicy: lazy
1 change: 1 addition & 0 deletions bundles/org.eclipse.cdt.lsp/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
class="org.eclipse.cdt.lsp.internal.server.CLanguageServerStreamConnectionProvider"
id="org.eclipse.cdt.lsp.server"
label="C/C++ Language Server"
serverInterface="org.eclipse.cdt.lsp.services.ClangdLanguageServer"
singleton="true">
</server>
<contentTypeMapping
Expand Down
Loading
0