To implement settings layers support in a JetBrains Rider plugin, you need to understand Rider's three-layer settings system and use the ReSharper Platform SDK APIs. Here's how to do it:
JetBrains Rider uses a layered settings system where higher layers override lower ones1:
- Personal layer - User-specific settings for the current solution
- Team-shared layer - Settings shared across the team (stored in VCS)
- Computer/Global layer - Settings stored on the local machine for all instances
The layers are applied top-down, with more specific layers overriding general ones2:
- Computer-level settings: Stored in user's LocalAppData, accessible to all ReSharper instances
- Solution-level settings:
.sln.dotSettings(team-shared, stored in VCS).sln.dotSettings.user(private user settings)
- Project-level settings:
.csproj.dotSettings(team-shared).csproj.dotSettings.user(private user settings)
Create a settings key class decorated with the SettingsKey attribute:
[SettingsKey(typeof(EnvironmentSettings), "My Plugin Settings")]
public class MyPluginSettingsKey
{
[SettingsEntry(false, "Enable Feature")]
public bool EnableFeature;
[SettingsEntry("Default Value", "My String Setting")]
public string MyStringSetting;
}Implement an options page that supports layer-based settings:
[OptionsPage(Pid, "My Plugin", typeof(FeaturesEnvironmentOptionsThemedIcons.CodeInspections),
ParentId = ToolsPage.PID)]
public class MyPluginOptionsPage : SimpleOptionsPage
{
private const string Pid = "MyPluginOptions";
public MyPluginOptionsPage([NotNull] Lifetime lifetime,
[NotNull] OptionsSettingsSmartContext optionsSettingsSmartContext)
: base(lifetime, optionsSettingsSmartContext)
{
// Add boolean option that respects layers
AddBoolOption((MyPluginSettingsKey key) => key.EnableFeature,
"Enable my plugin feature");
// Add string option
AddStringOption((MyPluginSettingsKey key) => key.MyStringSetting,
"My string setting");
}
}Use ISettingsStore with appropriate ContextRange to read settings:
public class MyPluginComponent
{
private readonly ISettingsStore _settingsStore;
public MyPluginComponent(ISettingsStore settingsStore)
{
_settingsStore = settingsStore;
}
public bool GetFeatureEnabled(IDataContext context)
{
// Use ContextRange.Smart to respect current layer editing mode
var contextBoundStore = _settingsStore.BindToContextTransient(
ContextRange.Smart.GetDataContext(context));
return contextBoundStore.GetValue((MyPluginSettingsKey key) => key.EnableFeature);
}
// Alternative: Bind to specific context ranges
public bool GetGlobalSetting()
{
var contextBoundStore = _settingsStore.BindToContextTransient(ContextRange.ApplicationWide);
return contextBoundStore.GetValue((MyPluginSettingsKey key) => key.EnableFeature);
}
}The key to layer support is using the correct ContextRange2:
ContextRange.ApplicationWide: Accesses computer-level settingsContextRange.Smart: Context depends on user's current settings editing mode, automatically respecting the active layerContextRange.ManuallyRestrictWritesToOneContext: For more granular control
public class LayerAwareSettingsViewModel : AAutomation
{
public IProperty<bool> FeatureEnabled { get; }
public LayerAwareSettingsViewModel(Lifetime lifetime, ISettingsStore settingsStore,
IDataContext dataContext)
{
// Bind to live context that respects layers
var contextBoundStore = settingsStore.BindToContextLive(lifetime,
ContextRange.Smart.GetDataContext(dataContext));
FeatureEnabled = contextBoundStore.GetValueProperty(lifetime,
(MyPluginSettingsKey key) => key.EnableFeature);
}
}- The
OptionsSettingsSmartContextin your options page automatically handles layer-aware reading and writing2 - Use
ContextRange.Smartwhen you want the system to automatically determine the appropriate layer based on user context2 - Settings defined this way will automatically appear in Rider's layer management UI and respect the layer hierarchy
- Team-shared settings will be stored in
.sln.dotSettingsfiles that can be committed to version control
This approach ensures your plugin settings integrate seamlessly with Rider's existing layer-based configuration system, allowing users to configure settings at the appropriate scope (personal, team, or global) just like built-in Rider features.