From b0dd6059798143861a7795822d84a7a63ef72fe2 Mon Sep 17 00:00:00 2001 From: jomillerOpen Date: Thu, 28 May 2026 09:18:38 -0400 Subject: [PATCH 1/5] [Feat] Have option to use tabs instead of spaces (forced override) Read the default text editor preferences from Eclipse instead of defaulting to spaces by default. --- .../core/format/FormatOptionProvider.java | 45 ++++++++++++++++++- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java index 8b06a164..c4b5caaf 100644 --- a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java +++ b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java @@ -9,7 +9,10 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.preferences.DefaultScope; +import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.lsp4j.FormattingOptions; +import org.osgi.service.prefs.Preferences; import com.microsoft.copilot.eclipse.core.CopilotCore; @@ -26,6 +29,9 @@ public class FormatOptionProvider { private static final String CPP_LANGUAGE_ID = "cpp"; private static final String[] CPP_LANGUAGE_EXTENSIONS = new String[] { "cpp", "c++", "cc", "cp", "cxx", "h", "h++", "hh", ".hpp", ".hxx", ".inc", ".inl", ".ipp", ".tcc", ".tpp" }; + private static final String EDITOR_PREF_NODE = "org.eclipse.ui.editors"; + private static final String TAB_WIDTH_KEY = "tabWidth"; + private static final String SPACES_FOR_TABS_KEY = "spacesForTabs"; private static final boolean DEFAULT_USE_SPACE = LanguageFormatReader.PREFERENCE_DEFAULT_TAB_CHAR.equals("space"); private static final int DEFAULT_TAB_SIZE = LanguageFormatReader.PREFERENCE_DEFAULT_TAB_SIZE; @@ -110,7 +116,7 @@ private FormattingOptions getLanguageFormat(IFile file) { if (languageFormatReaderForProject == null) { languageFormatReaderForProject = loadFormatReaderForTheProject(languageId, project); if (languageFormatReaderForProject == null) { - return new FormattingOptions(DEFAULT_TAB_SIZE, DEFAULT_USE_SPACE); + return getEclipseTextEditorFormattingOptions(); } projectToLanguageFormatReaderMap.put(project, languageFormatReaderForProject); } @@ -118,6 +124,41 @@ private FormattingOptions getLanguageFormat(IFile file) { return languageFormatReaderForProject.getFormattingOptions(); } + /** + * Attempts to read the Eclipse default text editor preferences for tab size and spaces-for-tabs. + * Falls back to hardcoded defaults if the preferences cannot be read. + */ + private FormattingOptions getEclipseTextEditorFormattingOptions() { + try { + Preferences instancePrefs = InstanceScope.INSTANCE.getNode(EDITOR_PREF_NODE); + Preferences defaultPrefs = DefaultScope.INSTANCE.getNode(EDITOR_PREF_NODE); + + int tabSize; + String instanceTabWidth = instancePrefs.get(TAB_WIDTH_KEY, null); + if (instanceTabWidth != null) { + tabSize = instancePrefs.getInt(TAB_WIDTH_KEY, DEFAULT_TAB_SIZE); + } else { + tabSize = defaultPrefs.getInt(TAB_WIDTH_KEY, DEFAULT_TAB_SIZE); + } + + boolean useSpaces; + String instanceSpaces = instancePrefs.get(SPACES_FOR_TABS_KEY, null); + if (instanceSpaces != null) { + useSpaces = instancePrefs.getBoolean(SPACES_FOR_TABS_KEY, DEFAULT_USE_SPACE); + } else { + useSpaces = defaultPrefs.getBoolean(SPACES_FOR_TABS_KEY, DEFAULT_USE_SPACE); + } + + return new FormattingOptions(tabSize, useSpaces); + } catch (Exception e) { + CopilotCore.LOGGER.info( + "Failed to read Eclipse text editor preferences, using defaults"); + return new FormattingOptions(DEFAULT_TAB_SIZE, DEFAULT_USE_SPACE); + } + } + + + private LanguageFormatReader loadFormatReaderForTheProject(String languageId, IProject project) { switch (languageId) { case JAVA_LANGUAGE_ID: @@ -129,4 +170,4 @@ private LanguageFormatReader loadFormatReaderForTheProject(String languageId, IP return null; } } -} \ No newline at end of file +} From 7b4bc6d68b3ee4ebabc80923b4120b8024b9e009 Mon Sep 17 00:00:00 2001 From: jomillerOpen Date: Fri, 29 May 2026 10:02:41 -0400 Subject: [PATCH 2/5] [Feat] Have option to use tabs instead of spaces (forced override) Switch to using the Platform.getPreferencesService() method instead, which will correctly account for the instances. --- .../core/format/FormatOptionProvider.java | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java index c4b5caaf..7fbb1e3c 100644 --- a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java +++ b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java @@ -9,10 +9,9 @@ import org.apache.commons.lang3.StringUtils; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.preferences.DefaultScope; -import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.lsp4j.FormattingOptions; -import org.osgi.service.prefs.Preferences; import com.microsoft.copilot.eclipse.core.CopilotCore; @@ -130,24 +129,21 @@ private FormattingOptions getLanguageFormat(IFile file) { */ private FormattingOptions getEclipseTextEditorFormattingOptions() { try { - Preferences instancePrefs = InstanceScope.INSTANCE.getNode(EDITOR_PREF_NODE); - Preferences defaultPrefs = DefaultScope.INSTANCE.getNode(EDITOR_PREF_NODE); - - int tabSize; - String instanceTabWidth = instancePrefs.get(TAB_WIDTH_KEY, null); - if (instanceTabWidth != null) { - tabSize = instancePrefs.getInt(TAB_WIDTH_KEY, DEFAULT_TAB_SIZE); - } else { - tabSize = defaultPrefs.getInt(TAB_WIDTH_KEY, DEFAULT_TAB_SIZE); - } - - boolean useSpaces; - String instanceSpaces = instancePrefs.get(SPACES_FOR_TABS_KEY, null); - if (instanceSpaces != null) { - useSpaces = instancePrefs.getBoolean(SPACES_FOR_TABS_KEY, DEFAULT_USE_SPACE); - } else { - useSpaces = defaultPrefs.getBoolean(SPACES_FOR_TABS_KEY, DEFAULT_USE_SPACE); - } + IPreferencesService service = Platform.getPreferencesService(); + + boolean useSpaces = service.getBoolean( + EDITOR_PREF_NODE, + SPACES_FOR_TABS_KEY, + DEFAULT_USE_SPACE, + null + ); + + int tabSize = service.getInt( + EDITOR_PREF_NODE, + TAB_WIDTH_KEY, + DEFAULT_TAB_SIZE, + null + ); return new FormattingOptions(tabSize, useSpaces); } catch (Exception e) { From 7be73f5c588277afdd75d6eb9d00e35d71e94ad1 Mon Sep 17 00:00:00 2001 From: jomillerOpen Date: Mon, 1 Jun 2026 10:38:51 -0400 Subject: [PATCH 3/5] [Feat] Have option to use tabs instead of spaces (forced override) Updated test to also retrieve the same values. --- .../completion/FormatOptionProviderTests.java | 36 ++++++++++++++++--- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java b/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java index c87449dc..00a54352 100644 --- a/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java +++ b/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java @@ -10,6 +10,8 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.preferences.IPreferencesService; import org.eclipse.lsp4j.FormattingOptions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -25,7 +27,11 @@ class FormatOptionProviderTests { private IFile mockFile; private IProject mockProject; + private static final String EDITOR_PREF_NODE = "org.eclipse.ui.editors"; + private static final String TAB_WIDTH_KEY = "tabWidth"; + private static final String SPACES_FOR_TABS_KEY = "spacesForTabs"; private static final int PREFERENCE_DEFAULT_TAB_SIZE = 4; + private static final boolean PREFERENCE_DEFAULT_USE_SPACE = true; @BeforeEach void setUp() { @@ -56,16 +62,38 @@ void testGetEclipseDefaultJavaTabCharAndSize() { void testGetCopilotDefaultTabCharAndSizeForUnknownLanguage() { when(mockFile.getFileExtension()).thenReturn("js"); - assertTrue(formatOptionProvider.useSpace(mockFile)); - assertEquals(PREFERENCE_DEFAULT_TAB_SIZE, formatOptionProvider.getTabSize(mockFile)); + FormattingOptions expectedFormattingOptions = getEclipseTextEditorFormattingOptions(); + assertEquals(expectedFormattingOptions.isInsertSpaces(), formatOptionProvider.useSpace(mockFile)); + assertEquals(expectedFormattingOptions.getTabSize(), formatOptionProvider.getTabSize(mockFile)); } @Test void testGetCopilotDefaultTabCharAndSizeForNoExtensionFile() { when(mockFile.getFileExtension()).thenReturn(null); - assertTrue(formatOptionProvider.useSpace(mockFile)); - assertEquals(PREFERENCE_DEFAULT_TAB_SIZE, formatOptionProvider.getTabSize(mockFile)); + FormattingOptions expectedFormattingOptions = getEclipseTextEditorFormattingOptions(); + assertEquals(expectedFormattingOptions.isInsertSpaces(), formatOptionProvider.useSpace(mockFile)); + assertEquals(expectedFormattingOptions.getTabSize(), formatOptionProvider.getTabSize(mockFile)); } + private FormattingOptions getEclipseTextEditorFormattingOptions() { + try { + IPreferencesService service = Platform.getPreferencesService(); + boolean useSpaces = service.getBoolean( + EDITOR_PREF_NODE, + SPACES_FOR_TABS_KEY, + PREFERENCE_DEFAULT_USE_SPACE, + null + ); + int tabSize = service.getInt( + EDITOR_PREF_NODE, + TAB_WIDTH_KEY, + PREFERENCE_DEFAULT_TAB_SIZE, + null + ); + return new FormattingOptions(tabSize, useSpaces); + } catch (Exception e) { + return new FormattingOptions(PREFERENCE_DEFAULT_TAB_SIZE, PREFERENCE_DEFAULT_USE_SPACE); + } + } } From a65ad5e7b85ce2837b7e36f99d1b8e481fea4757 Mon Sep 17 00:00:00 2001 From: jomillerOpen Date: Tue, 2 Jun 2026 14:30:24 -0400 Subject: [PATCH 4/5] [Feat] Have option to use tabs instead of spaces (forced override) Return the Eclipse settings when the file isn't part of a project or doesn't have an extension. --- .../copilot/eclipse/core/format/FormatOptionProvider.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java index 7fbb1e3c..b738929f 100644 --- a/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java +++ b/com.microsoft.copilot.eclipse.core/src/com/microsoft/copilot/eclipse/core/format/FormatOptionProvider.java @@ -90,13 +90,13 @@ private FormattingOptions getLanguageFormat(IFile file) { IProject project = file.getProject(); if (project == null) { CopilotCore.LOGGER.info("Project is null for file: " + file.getName() + "default format will be applied."); - return null; + return getEclipseTextEditorFormattingOptions(); } String fileExtension = file.getFileExtension(); if (StringUtils.isEmpty(fileExtension)) { CopilotCore.LOGGER.info("File extension is null or empty for file: " + file.getName()); - return null; + return getEclipseTextEditorFormattingOptions(); } else { fileExtension = fileExtension.toLowerCase(); } From 3f680c2de39f8951faee3cbfe5ba33783e1840a0 Mon Sep 17 00:00:00 2001 From: jomillerOpen Date: Wed, 3 Jun 2026 15:29:20 -0400 Subject: [PATCH 5/5] [Feat] Have option to use tabs instead of spaces (forced override) Updated test to set the preferences and then test. --- .../completion/FormatOptionProviderTests.java | 53 ++++++------------- 1 file changed, 16 insertions(+), 37 deletions(-) diff --git a/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java b/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java index 00a54352..eeeb756d 100644 --- a/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java +++ b/com.microsoft.copilot.eclipse.core.test/src/com/microsoft/copilot/eclipse/core/completion/FormatOptionProviderTests.java @@ -10,12 +10,15 @@ import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; -import org.eclipse.core.runtime.Platform; -import org.eclipse.core.runtime.preferences.IPreferencesService; +import org.eclipse.core.runtime.preferences.IEclipsePreferences; +import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.lsp4j.FormattingOptions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.NullSource; +import org.junit.jupiter.params.provider.ValueSource; import org.mockito.junit.jupiter.MockitoExtension; import com.microsoft.copilot.eclipse.core.format.FormatOptionProvider; @@ -30,8 +33,6 @@ class FormatOptionProviderTests { private static final String EDITOR_PREF_NODE = "org.eclipse.ui.editors"; private static final String TAB_WIDTH_KEY = "tabWidth"; private static final String SPACES_FOR_TABS_KEY = "spacesForTabs"; - private static final int PREFERENCE_DEFAULT_TAB_SIZE = 4; - private static final boolean PREFERENCE_DEFAULT_USE_SPACE = true; @BeforeEach void setUp() { @@ -58,42 +59,20 @@ void testGetEclipseDefaultJavaTabCharAndSize() { assertEquals(tabSize, formatOptionProvider.getTabSize(mockFile)); } - @Test - void testGetCopilotDefaultTabCharAndSizeForUnknownLanguage() { - when(mockFile.getFileExtension()).thenReturn("js"); - - FormattingOptions expectedFormattingOptions = getEclipseTextEditorFormattingOptions(); - assertEquals(expectedFormattingOptions.isInsertSpaces(), formatOptionProvider.useSpace(mockFile)); - assertEquals(expectedFormattingOptions.getTabSize(), formatOptionProvider.getTabSize(mockFile)); - } + @ParameterizedTest @NullSource @ValueSource(strings = { "js" }) + void testUsesEclipseTextEditorFormattingOptionsForUnknownOrNoExtension(String extension) { + when(mockFile.getFileExtension()).thenReturn(extension); - @Test - void testGetCopilotDefaultTabCharAndSizeForNoExtensionFile() { - when(mockFile.getFileExtension()).thenReturn(null); + // Set the Eclipse preferences to be something other than the default (false, 4) + setEditorFormattingPreferences(true, 2); - FormattingOptions expectedFormattingOptions = getEclipseTextEditorFormattingOptions(); - assertEquals(expectedFormattingOptions.isInsertSpaces(), formatOptionProvider.useSpace(mockFile)); - assertEquals(expectedFormattingOptions.getTabSize(), formatOptionProvider.getTabSize(mockFile)); + assertTrue(formatOptionProvider.useSpace(mockFile)); + assertEquals(2, formatOptionProvider.getTabSize(mockFile)); } - private FormattingOptions getEclipseTextEditorFormattingOptions() { - try { - IPreferencesService service = Platform.getPreferencesService(); - boolean useSpaces = service.getBoolean( - EDITOR_PREF_NODE, - SPACES_FOR_TABS_KEY, - PREFERENCE_DEFAULT_USE_SPACE, - null - ); - int tabSize = service.getInt( - EDITOR_PREF_NODE, - TAB_WIDTH_KEY, - PREFERENCE_DEFAULT_TAB_SIZE, - null - ); - return new FormattingOptions(tabSize, useSpaces); - } catch (Exception e) { - return new FormattingOptions(PREFERENCE_DEFAULT_TAB_SIZE, PREFERENCE_DEFAULT_USE_SPACE); - } + private void setEditorFormattingPreferences(boolean useSpaces, int tabSize) { + IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(EDITOR_PREF_NODE); + prefs.putBoolean(SPACES_FOR_TABS_KEY, useSpaces); + prefs.putInt(TAB_WIDTH_KEY, tabSize); } }