diff --git a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF index 7b5857390b5..fceb0be4b98 100644 --- a/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF +++ b/core/org.eclipse.cdt.ui/META-INF/MANIFEST.MF @@ -22,7 +22,11 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.internal.ui.dialogs;x-internal:=true, org.eclipse.cdt.internal.ui.dialogs.cpaths;x-internal:=true, org.eclipse.cdt.internal.ui.dnd;x-internal:=true, - org.eclipse.cdt.internal.ui.editor;x-friends:="org.eclipse.cdt.codan.ui,org.eclipse.cdt.codan.ui.cxx,org.eclipse.cdt.dsf.ui", + org.eclipse.cdt.internal.ui.editor; + x-friends:="org.eclipse.cdt.codan.ui, + org.eclipse.cdt.codan.ui.cxx, + org.eclipse.cdt.dsf.ui, + org.eclipse.cdt.lsp", org.eclipse.cdt.internal.ui.editor.asm;x-internal:=true, org.eclipse.cdt.internal.ui.filters;x-internal:=true, org.eclipse.cdt.internal.ui.help;x-internal:=true, @@ -51,6 +55,7 @@ Export-Package: org.eclipse.cdt.internal.corext;x-internal:=true, org.eclipse.cdt.internal.ui.resources, org.eclipse.cdt.internal.ui.search;x-internal:=true, org.eclipse.cdt.internal.ui.search.actions;x-internal:=true, + org.eclipse.cdt.internal.ui.switchtolsp;x-friends:="org.eclipse.cdt.lsp", org.eclipse.cdt.internal.ui.text;x-friends:="org.eclipse.cdt.codan.ui.cxx,org.eclipse.cdt.dsf.ui", org.eclipse.cdt.internal.ui.text.asm;x-internal:=true, org.eclipse.cdt.internal.ui.text.c.hover;x-internal:=true, diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java index ce433080c9b..c78000322a5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CEditor.java @@ -74,6 +74,7 @@ import org.eclipse.cdt.internal.ui.search.IOccurrencesFinder; import org.eclipse.cdt.internal.ui.search.IOccurrencesFinder.OccurrenceLocation; import org.eclipse.cdt.internal.ui.search.OccurrencesFinder; import org.eclipse.cdt.internal.ui.search.actions.SelectionSearchGroup; +import org.eclipse.cdt.internal.ui.switchtolsp.ISwitchToLsp; import org.eclipse.cdt.internal.ui.text.CHeuristicScanner; import org.eclipse.cdt.internal.ui.text.CPairMatcher; import org.eclipse.cdt.internal.ui.text.CSourceViewerScalableConfiguration; @@ -111,6 +112,7 @@ import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.ListenerList; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.SafeRunner; import org.eclipse.core.runtime.Status; import org.eclipse.core.runtime.content.IContentType; import org.eclipse.core.runtime.jobs.Job; @@ -2786,8 +2788,10 @@ public class CEditor extends TextEditor @Override protected ISourceViewer createSourceViewer(Composite parent, IVerticalRuler ruler, int styles) { + Composite editorComposite = createTryLspBanner(parent); + IPreferenceStore store = getPreferenceStore(); - AdaptedSourceViewer cSourceViewer = new AdaptedSourceViewer(parent, ruler, getOverviewRuler(), + AdaptedSourceViewer cSourceViewer = new AdaptedSourceViewer(editorComposite, ruler, getOverviewRuler(), isOverviewRulerVisible(), styles, store); /* @@ -2818,6 +2822,29 @@ public class CEditor extends TextEditor return cSourceViewer; } + /** + * Wraps {@link ISwitchToLsp#createTryLspEditor(org.eclipse.ui.texteditor.ITextEditor, Composite)} + * with the needed service access + fallback checks. + * + * If the {@link ISwitchToLsp} service doesn't exist, or fails, this method + * is a no-op that simply returns its input. + * + * @see ISwitchToLsp#createTryLspEditor(org.eclipse.ui.texteditor.ITextEditor, Composite) + */ + private Composite createTryLspBanner(Composite parent) { + Composite editorComposite = SafeRunner.run(() -> { + ISwitchToLsp switchToLsp = PlatformUI.getWorkbench().getService(ISwitchToLsp.class); + if (switchToLsp != null) { + return switchToLsp.createTryLspEditor(CEditor.this, parent); + } + return null; + }); + if (editorComposite == null) { + editorComposite = parent; + } + return editorComposite; + } + /** Outliner context menu Id */ protected String fOutlinerContextMenuId; diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/switchtolsp/ISwitchToLsp.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/switchtolsp/ISwitchToLsp.java new file mode 100644 index 00000000000..5a28a213aa4 --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/switchtolsp/ISwitchToLsp.java @@ -0,0 +1,39 @@ +/******************************************************************************* + * Copyright (c) 2025 Kichwa Coders Canada Inc. 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 + *******************************************************************************/ + +package org.eclipse.cdt.internal.ui.switchtolsp; + +import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.ui.texteditor.ITextEditor; + +/** + * This interface can be implemented by CDT-LSP to display a banner in the {@link CEditor} + * to encourage users to try the new C/C++ editing experience based on CDT/LSP + * + * See org.eclipse.cdt.lsp/OSGI-INF/org.eclipse.cdt.lsp.internal.switchtolsp.SwitchToLsp.xml + * for the use. + * + * This interface is not public API, it is provided as a hook for CDT LSP and may + * be changed at any point. + */ +public interface ISwitchToLsp { + + /** + * Create the banner controls for the "try new experience" + * + * @param part the editor part that the banner is added on + * @param parent the parent control + * @return the new parent control the editor should use + */ + Composite createTryLspEditor(ITextEditor part, Composite parent); + +}