Skip to content

Commit

Permalink
add URIEnableCache class
Browse files Browse the repository at this point in the history
  • Loading branch information
ghentschke committed Feb 6, 2025
1 parent b5820e4 commit 4d560b3
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@
import org.eclipse.core.runtime.preferences.PreferenceMetadata;

public interface EditorMetadata extends ConfigurationMetadata {
/**
* @since 3.0
*/
public static final String PREFER_LSP_KEY = "prefer_lsp"; //$NON-NLS-1$

/**
* The predefined metadata for the "Prefer C/C++ Editor (LSP)" option
Expand All @@ -26,8 +30,7 @@ public interface EditorMetadata extends ConfigurationMetadata {
* @since 3.0
*/
PreferenceMetadata<Boolean> preferLspEditor = new PreferenceMetadata<>(Boolean.class, //
"prefer_lsp", //$NON-NLS-1$
false, //
PREFER_LSP_KEY, false, //
LspUiMessages.LspEditorConfigurationPage_preferLspEditor,
LspUiMessages.LspEditorConfigurationPage_preferLspEditor_description);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

package org.eclipse.cdt.lsp.editor;

import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;

public interface EditorOptions {

/**
Expand Down Expand Up @@ -42,4 +44,14 @@ public interface EditorOptions {
*/
boolean formatEditedLines();

/**
* @since 3.0
*/
void addPreferenceChangedListener(IPreferenceChangeListener listener);

/**
* @since 3.0
*/
void removePreferenceChangedListener(IPreferenceChangeListener listener);

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@

package org.eclipse.cdt.lsp.internal.editor;

import java.util.Optional;

import org.eclipse.cdt.lsp.PreferredOptions;
import org.eclipse.cdt.lsp.editor.EditorMetadata;
import org.eclipse.cdt.lsp.editor.EditorOptions;
import org.eclipse.cdt.lsp.editor.LanguageServerEnable;
import org.eclipse.cdt.lsp.internal.server.URIEnableCache;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IScopeContext;

public final class EditorPreferredOptions extends PreferredOptions implements EditorOptions, LanguageServerEnable {
Expand All @@ -26,6 +30,7 @@ public EditorPreferredOptions(EditorMetadata metadata, String qualifier, IScopeC
LanguageServerEnable enable) {
super(metadata, qualifier, scopes);
this.enable = enable;
this.addPreferenceChangedListener(URIEnableCache.getInstance());
}

@Override
Expand Down Expand Up @@ -56,4 +61,18 @@ public boolean isEnabledFor(IProject project) {
return booleanValue(EditorMetadata.preferLspEditor);
}

@Override
public void addPreferenceChangedListener(IPreferenceChangeListener listener) {
for (var scope : scopes) {
Optional.ofNullable(scope.getNode(qualifier)).ifPresent(n -> n.addPreferenceChangeListener(listener));
}
}

@Override
public void removePreferenceChangedListener(IPreferenceChangeListener listener) {
for (var scope : scopes) {
Optional.ofNullable(scope.getNode(qualifier)).ifPresent(n -> n.removePreferenceChangeListener(listener));
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@

import java.io.File;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import org.eclipse.cdt.core.model.ICProject;
Expand All @@ -39,8 +37,8 @@ public class HasLanguageServerPropertyTester extends PropertyTester {
private final ICLanguageServerProvider cLanguageServerProvider;
private final ServiceCaller<InitialUri> initial;
private final ServiceCaller<IWorkspace> workspace;
private final URIEnableCache cache = URIEnableCache.getInstance();
private Optional<IProject> project;
private final Map<URI, Boolean> cache = new HashMap<>();

public HasLanguageServerPropertyTester() {
this.cLanguageServerProvider = LspPlugin.getDefault().getCLanguageServerProvider();
Expand All @@ -64,10 +62,10 @@ public boolean test(Object receiver, String property, Object[] args, Object expe
}
// when getProject is empty, it's an external file: Check if the file is already opened, if not check the active editor:
var isEnabled = enabledFor(uri);
cache.put(uri, isEnabled);
if (isEnabled) {
initial.call(iu -> iu.register(uri));
}
cache.put(uri, isEnabled);
return isEnabled;
} else if (receiver instanceof ITranslationUnit) {
// called to enable the LS based CSymbolsContentProvider:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
/*******************************************************************************
* Copyright (c) 2025 Contributors to the Eclipse Foundation.
* 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:
* See git history
*******************************************************************************/

package org.eclipse.cdt.lsp.internal.server;

import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;

import org.eclipse.cdt.internal.core.LRUCache;
import org.eclipse.cdt.lsp.editor.EditorMetadata;
import org.eclipse.core.internal.content.ContentTypeManager;
import org.eclipse.core.runtime.content.IContentTypeManager.ContentTypeChangeEvent;
import org.eclipse.core.runtime.content.IContentTypeManager.IContentTypeChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.ui.IPartListener;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.genericeditor.ExtensionBasedTextEditor;

/**
* Caches the enable status for a given resource URI. Used by {@link HasLanguageServerPropertyTester#test(Object, String, Object[], Object)}
* The cache is getting cleared: on changes in the C/C++ content types or the prefer LSP editor option has been changed (workspace or project level).
* A resource URI shall be removed from the cache if it's getting closed in the editor.
*/
public final class URIEnableCache
implements IPreferenceChangeListener, IContentTypeChangeListener, IPartListener, IWindowListener {
private static final String C_SOURCE = "org.eclipse.cdt.core.cSource"; //$NON-NLS-1$
private static final String CXX_SOURCE = "org.eclipse.cdt.core.cxxSource"; //$NON-NLS-1$
private static final String C_HEADER = "org.eclipse.cdt.core.cHeader"; //$NON-NLS-1$
private static final String CXX_HEADER = "org.eclipse.cdt.core.cxxHeader"; //$NON-NLS-1$
private static final Map<URI, Boolean> cache = Collections.synchronizedMap(new LRUCache<>(100));
private static URIEnableCache instance = null;

private URIEnableCache() {
ContentTypeManager.getInstance().addContentTypeChangeListener(this);
if (PlatformUI.isWorkbenchRunning()) {
var workbench = PlatformUI.getWorkbench();
workbench.addWindowListener(this);
Arrays.stream(workbench.getWorkbenchWindows()).map(IWorkbenchWindow::getPages).flatMap(Arrays::stream)
.forEach(p -> p.addPartListener(this));
}
}

public static void stop() {
if (instance != null) {
var workbench = PlatformUI.getWorkbench();
workbench.removeWindowListener(instance);
Arrays.stream(workbench.getWorkbenchWindows()).map(IWorkbenchWindow::getPages).flatMap(Arrays::stream)
.forEach(p -> p.removePartListener(instance));
cache.clear();
}
}

public static synchronized URIEnableCache getInstance() {
if (instance == null) {
instance = new URIEnableCache();
}
return instance;
}

public Boolean get(URI uri) {
return cache.get(uri);
}

public void put(URI uri, Boolean value) {
cache.put(uri, value);
}

@Override
public void preferenceChange(PreferenceChangeEvent event) {
if (EditorMetadata.PREFER_LSP_KEY.contentEquals(event.getKey())) {
cache.clear();
}
}

@Override
public void contentTypeChanged(ContentTypeChangeEvent event) {
var id = event.getContentType().getId();
if (C_SOURCE.contentEquals(id) || CXX_SOURCE.contentEquals(id) || C_HEADER.contentEquals(id)
|| CXX_HEADER.contentEquals(id)) {
cache.clear();
}
}

@Override
public void partActivated(IWorkbenchPart part) {
// do nothing
}

@Override
public void partBroughtToTop(IWorkbenchPart part) {
// do nothing
}

@Override
public void partClosed(IWorkbenchPart part) {
if (part instanceof ExtensionBasedTextEditor editor) {
Optional.ofNullable(LSPEclipseUtils.toUri(editor.getEditorInput())).ifPresent(uri -> cache.remove(uri));
}
}

@Override
public void partDeactivated(IWorkbenchPart part) {
// do nothing
}

@Override
public void partOpened(IWorkbenchPart part) {
// do nothing
}

@Override
public void windowActivated(IWorkbenchWindow window) {
// do nothing
}

@Override
public void windowDeactivated(IWorkbenchWindow window) {
// do nothing
}

@Override
public void windowClosed(IWorkbenchWindow window) {
Arrays.stream(window.getPages()).forEach(p -> p.removePartListener(this));
}

@Override
public void windowOpened(IWorkbenchWindow window) {
Arrays.stream(window.getPages()).forEach(p -> p.addPartListener(this));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.logging.Logger;

import org.eclipse.cdt.lsp.internal.server.CLanguageServerRegistry;
import org.eclipse.cdt.lsp.internal.server.URIEnableCache;
import org.eclipse.cdt.lsp.server.ICLanguageServerProvider;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;
Expand Down Expand Up @@ -58,6 +59,7 @@ public void start(BundleContext context) throws Exception {

@Override
public void stop(BundleContext context) throws Exception {
URIEnableCache.stop();
plugin = null;
super.stop(context);
}
Expand Down

0 comments on commit 4d560b3

Please sign in to comment.