Skip to content
This repository was archived by the owner on Oct 16, 2020. It is now read-only.

Commit 8a1c65b

Browse files
committed
Persisting and restoring formatter settings on global level, support for presets from NR.
1 parent ad4040a commit 8a1c65b

19 files changed

Lines changed: 486 additions & 273 deletions

src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.addin

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@
150150
<ContextActionOptionPanel id="ContextActions" path="/SharpDevelop/ViewContent/TextEditor/C#/ContextActions"/>
151151
<OptionPanel id="Formatting"
152152
label="Formatting"
153-
class="CSharpBinding.OptionPanels.CSharpFormattingOptionPanel"/>
153+
class="CSharpBinding.OptionPanels.CSharpGlobalFormattingOptionPanel"/>
154154
</OptionPanel>
155155
</Path>
156156

src/AddIns/BackendBindings/CSharpBinding/Project/CSharpBinding.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@
6262
</Reference>
6363
<Reference Include="System.Xml" />
6464
<Reference Include="Microsoft.Build.Engine" />
65+
<Reference Include="System.Xml.Linq">
66+
<RequiredTargetFramework>3.5</RequiredTargetFramework>
67+
</Reference>
6568
<Reference Include="WindowsBase">
6669
<RequiredTargetFramework>3.0</RequiredTargetFramework>
6770
</Reference>
@@ -82,6 +85,7 @@
8285
<Compile Include="Src\Completion\XmlDocCompletionData.cs" />
8386
<Compile Include="Src\FormattingStrategy\CSharpFormattingOptionsContainer.cs" />
8487
<Compile Include="Src\FormattingStrategy\CSharpFormatter.cs" />
88+
<Compile Include="Src\FormattingStrategy\CSharpFormattingOptionsPersistence.cs" />
8589
<Compile Include="Src\FormattingStrategy\FormattingOptionBinding.cs" />
8690
<Compile Include="Src\FormsDesigner\CSharpDesignerGenerator.cs" />
8791
<Compile Include="Src\FormsDesigner\CSharpDesignerLoader.cs" />

src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideCompletionData.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -98,8 +98,9 @@ public override void Complete(CompletionContext context)
9898

9999
var document = context.Editor.Document;
100100
StringWriter w = new StringWriter();
101-
var formattingOptions = FormattingOptionsFactory.CreateSharpDevelop();
102-
var segmentDict = SegmentTrackingOutputFormatter.WriteNode(w, entityDeclaration, formattingOptions, context.Editor.Options);
101+
var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(contextAtCaret.Compilation.GetProject());
102+
var segmentDict = SegmentTrackingOutputFormatter.WriteNode(
103+
w, entityDeclaration, formattingOptions.OptionsContainer.GetEffectiveOptions(), context.Editor.Options);
103104

104105
using (document.OpenUndoGroup()) {
105106
string newText = w.ToString().TrimEnd();
@@ -109,7 +110,7 @@ public override void Complete(CompletionContext context)
109110
var segment = segmentDict[throwStatement];
110111
context.Editor.Select(declarationBegin + segment.Offset, segment.Length);
111112
}
112-
CSharpFormatterHelper.Format(context.Editor, declarationBegin, newText.Length, formattingOptions);
113+
CSharpFormatterHelper.Format(context.Editor, declarationBegin, newText.Length, formattingOptions.OptionsContainer);
113114
}
114115
}
115116

src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideEqualsGetHashCodeCompletionData.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,9 @@ public override void Complete(CompletionContext context)
8484

8585
var document = context.Editor.Document;
8686
StringWriter w = new StringWriter();
87-
var formattingOptions = FormattingOptionsFactory.CreateSharpDevelop();
88-
var segmentDict = SegmentTrackingOutputFormatter.WriteNode(w, entityDeclaration, formattingOptions, context.Editor.Options);
87+
var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(contextAtCaret.Compilation.GetProject());
88+
var segmentDict = SegmentTrackingOutputFormatter.WriteNode(
89+
w, entityDeclaration, formattingOptions.OptionsContainer.GetEffectiveOptions(), context.Editor.Options);
8990

9091
using (document.OpenUndoGroup()) {
9192
InsertionContext insertionContext = new InsertionContext(context.Editor.GetService(typeof(TextArea)) as TextArea, declarationBegin);
@@ -98,7 +99,7 @@ public override void Complete(CompletionContext context)
9899
var segment = segmentDict[throwStatement];
99100
context.Editor.Select(declarationBegin + segment.Offset, segment.Length);
100101
}
101-
CSharpFormatterHelper.Format(context.Editor, declarationBegin, newText.Length, formattingOptions);
102+
CSharpFormatterHelper.Format(context.Editor, declarationBegin, newText.Length, formattingOptions.OptionsContainer);
102103

103104
var refactoringContext = SDRefactoringContext.Create(context.Editor, CancellationToken.None);
104105
var typeResolveContext = refactoringContext.GetTypeResolveContext();

src/AddIns/BackendBindings/CSharpBinding/Project/Src/Completion/OverrideToStringCompletionData.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
using ICSharpCode.AvalonEdit.Editing;
2525
using ICSharpCode.AvalonEdit.Snippets;
2626
using ICSharpCode.NRefactory.Editor;
27+
using ICSharpCode.SharpDevelop;
2728
using CSharpBinding.FormattingStrategy;
2829
using ICSharpCode.NRefactory.CSharp;
2930
using ICSharpCode.NRefactory.CSharp.Refactoring;
@@ -80,8 +81,9 @@ public override void Complete(CompletionContext context)
8081

8182
var document = context.Editor.Document;
8283
StringWriter w = new StringWriter();
83-
var formattingOptions = FormattingOptionsFactory.CreateSharpDevelop();
84-
var segmentDict = SegmentTrackingOutputFormatter.WriteNode(w, entityDeclaration, formattingOptions, context.Editor.Options);
84+
var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(contextAtCaret.Compilation.GetProject());
85+
var segmentDict = SegmentTrackingOutputFormatter.WriteNode(
86+
w, entityDeclaration, formattingOptions.OptionsContainer.GetEffectiveOptions(), context.Editor.Options);
8587

8688
using (document.OpenUndoGroup()) {
8789
InsertionContext insertionContext = new InsertionContext(context.Editor.GetService(typeof(TextArea)) as TextArea, declarationBegin);
@@ -94,7 +96,7 @@ public override void Complete(CompletionContext context)
9496
var segment = segmentDict[throwStatement];
9597
context.Editor.Select(declarationBegin + segment.Offset, segment.Length);
9698
}
97-
CSharpFormatterHelper.Format(context.Editor, declarationBegin, newText.Length, formattingOptions);
99+
CSharpFormatterHelper.Format(context.Editor, declarationBegin, newText.Length, formattingOptions.OptionsContainer);
98100

99101
var refactoringContext = SDRefactoringContext.Create(context.Editor, CancellationToken.None);
100102
var typeResolveContext = refactoringContext.GetTypeResolveContext();

src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormatter.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424

2525
namespace CSharpBinding.FormattingStrategy
2626
{
27-
public class CSharpFormatterHelper
27+
internal class CSharpFormatterHelper
2828
{
2929
/// <summary>
3030
/// Formats the specified part of the document.
3131
/// </summary>
32-
public static void Format(ITextEditor editor, int offset, int length, CSharpFormattingOptions options)
32+
public static void Format(ITextEditor editor, int offset, int length, CSharpFormattingOptionsContainer optionsContainer)
3333
{
34-
var formatter = new CSharpFormatter(options, editor.ToEditorOptions());
34+
var formatter = new CSharpFormatter(optionsContainer.GetEffectiveOptions(), editor.ToEditorOptions());
3535
formatter.AddFormattingRegion(new DomRegion(editor.Document.GetLocation(offset), editor.Document.GetLocation(offset + length)));
3636
var changes = formatter.AnalyzeFormatting(editor.Document, SyntaxTree.Parse(editor.Document));
3737
changes.ApplyChanges(offset, length);

src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormattingStrategy/CSharpFormattingOptionsContainer.cs

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@
2121
using System.ComponentModel;
2222
using System.Linq.Expressions;
2323
using System.Reflection;
24+
using System.Text;
25+
using System.Xml;
26+
using ICSharpCode.Core;
2427
using ICSharpCode.NRefactory.CSharp;
2528

2629
namespace CSharpBinding.FormattingStrategy
@@ -29,30 +32,18 @@ namespace CSharpBinding.FormattingStrategy
2932
/// Generic container for C# formatting options that can be chained together from general to specific and inherit
3033
/// options from parent.
3134
/// </summary>
32-
public class CSharpFormattingOptionsContainer : INotifyPropertyChanged
35+
internal class CSharpFormattingOptionsContainer : INotifyPropertyChanged
3336
{
3437
CSharpFormattingOptionsContainer parent;
3538
CSharpFormattingOptions cachedOptions;
3639

37-
HashSet<string> activeOptions;
40+
readonly HashSet<string> activeOptions;
3841

39-
internal CSharpFormattingOptionsContainer()
42+
internal CSharpFormattingOptionsContainer(CSharpFormattingOptionsContainer parent = null)
4043
{
41-
parent = null;
42-
activeOptions = new HashSet<string>();
43-
cachedOptions = FormattingOptionsFactory.CreateEmpty();
44-
}
45-
46-
internal CSharpFormattingOptionsContainer(CSharpFormattingOptions options)
47-
{
48-
parent = null;
49-
activeOptions = new HashSet<string>();
50-
51-
cachedOptions = options;
52-
// Activate all options
53-
foreach (var property in typeof(CSharpFormattingOptions).GetProperties()) {
54-
activeOptions.Add(property.Name);
55-
}
44+
this.parent = parent;
45+
this.activeOptions = new HashSet<string>();
46+
Reset();
5647
}
5748

5849
public CSharpFormattingOptionsContainer Parent
@@ -61,16 +52,23 @@ public CSharpFormattingOptionsContainer Parent
6152
{
6253
return parent;
6354
}
64-
set
65-
{
66-
if (parent != null) {
67-
parent.PropertyChanged += HandlePropertyChanged;
55+
}
56+
57+
/// <summary>
58+
/// Resets all container's options to given <see cref="ICSharpCode.NRefactory.CSharp.CSharpFormattingOptions"/> instance.
59+
/// </summary>
60+
/// <param name="options">Option values to set in container. <c>null</c> (default) to use empty options.</param>
61+
public void Reset(CSharpFormattingOptions options = null)
62+
{
63+
activeOptions.Clear();
64+
cachedOptions = options ?? FormattingOptionsFactory.CreateEmpty();
65+
if ((options != null) || (parent == null)) {
66+
// Activate all options
67+
foreach (var property in typeof(CSharpFormattingOptions).GetProperties()) {
68+
activeOptions.Add(property.Name);
6869
}
69-
parent = value;
70-
parent.PropertyChanged += HandlePropertyChanged;
71-
cachedOptions = CreateOptions();
72-
OnPropertyChanged("Parent");
7370
}
71+
OnPropertyChanged(null);
7472
}
7573

7674
#region INotifyPropertyChanged implementation
@@ -198,6 +196,7 @@ public void SetOption(string option, object value)
198196
propertyInfo.SetValue(cachedOptions, GetEffectiveOption(option));
199197
}
200198
}
199+
OnPropertyChanged(option);
201200
}
202201

203202
/// <summary>
@@ -245,5 +244,40 @@ private CSharpFormattingOptions CreateOptions()
245244

246245
return outputOptions;
247246
}
247+
248+
public void Load(Properties parentProperties)
249+
{
250+
if (parentProperties == null)
251+
throw new ArgumentNullException("parentProperties");
252+
253+
Properties formatProperties = parentProperties.NestedProperties("CSharpFormatting");
254+
if (formatProperties != null) {
255+
foreach (var key in formatProperties.Keys) {
256+
try {
257+
object val = formatProperties.Get(key, (object) null);
258+
SetOption(key, val);
259+
} catch (Exception) {
260+
// Silently ignore loading error, then this property will be "as parent" automatically
261+
}
262+
}
263+
}
264+
}
265+
266+
public void Save(Properties parentProperties)
267+
{
268+
if (parentProperties == null)
269+
throw new ArgumentNullException("parentProperties");
270+
271+
// Create properties container from container settings
272+
Properties formatProperties = new Properties();
273+
foreach (var activeOption in activeOptions) {
274+
object val = GetOption(activeOption);
275+
if (val != null) {
276+
formatProperties.Set(activeOption, val);
277+
}
278+
}
279+
280+
parentProperties.SetNestedProperties("CSharpFormatting", formatProperties);
281+
}
248282
}
249283
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// Copyright (c) 2014 AlphaSierraPapa for the SharpDevelop Team
2+
//
3+
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
4+
// software and associated documentation files (the "Software"), to deal in the Software
5+
// without restriction, including without limitation the rights to use, copy, modify, merge,
6+
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
7+
// to whom the Software is furnished to do so, subject to the following conditions:
8+
//
9+
// The above copyright notice and this permission notice shall be included in all copies or
10+
// substantial portions of the Software.
11+
//
12+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
13+
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14+
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
15+
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
16+
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
17+
// DEALINGS IN THE SOFTWARE.
18+
19+
using System;
20+
using System.Collections.Generic;
21+
using ICSharpCode.Core;
22+
using ICSharpCode.NRefactory.CSharp;
23+
using ICSharpCode.SharpDevelop;
24+
using ICSharpCode.SharpDevelop.Project;
25+
26+
namespace CSharpBinding.FormattingStrategy
27+
{
28+
/// <summary>
29+
/// Persistence helper for C# formatting options.
30+
/// </summary>
31+
internal class CSharpFormattingOptionsPersistence
32+
{
33+
static Dictionary<string, CSharpFormattingOptionsPersistence> projectOptions;
34+
35+
static CSharpFormattingOptionsPersistence()
36+
{
37+
projectOptions = new Dictionary<string, CSharpFormattingOptionsPersistence>();
38+
39+
// Load global settings
40+
GlobalOptions = new CSharpFormattingOptionsPersistence(
41+
SD.PropertyService.MainPropertiesContainer, new CSharpFormattingOptionsContainer());
42+
43+
// Handlers for solution loading/unloading
44+
SD.ProjectService.SolutionOpened += SolutionOpened;
45+
SD.ProjectService.SolutionClosed += SolutionClosed;
46+
}
47+
48+
public static CSharpFormattingOptionsPersistence GlobalOptions
49+
{
50+
get;
51+
private set;
52+
}
53+
54+
public static CSharpFormattingOptionsPersistence SolutionOptions
55+
{
56+
get;
57+
private set;
58+
}
59+
60+
public static CSharpFormattingOptionsPersistence GetProjectOptions(IProject project)
61+
{
62+
var csproject = project as CSharpProject;
63+
if (csproject != null) {
64+
string key = project.FileName;
65+
if (!projectOptions.ContainsKey(key)) {
66+
// Lazily create options container
67+
projectOptions[key] = new CSharpFormattingOptionsPersistence(
68+
csproject.ExtensionProperties,
69+
new CSharpFormattingOptionsContainer(SolutionOptions.OptionsContainer));
70+
}
71+
72+
return projectOptions[key];
73+
}
74+
75+
return SolutionOptions ?? GlobalOptions;
76+
}
77+
78+
static void SolutionOpened(object sender, SolutionEventArgs e)
79+
{
80+
// Load solution settings
81+
SolutionOptions = new CSharpFormattingOptionsPersistence(
82+
e.Solution.GlobalPreferences,
83+
new CSharpFormattingOptionsContainer(GlobalOptions.OptionsContainer));
84+
}
85+
86+
static void SolutionClosed(object sender, SolutionEventArgs e)
87+
{
88+
SolutionOptions = null;
89+
projectOptions.Clear();
90+
}
91+
92+
readonly Properties propertiesContainer;
93+
readonly CSharpFormattingOptionsContainer optionsContainer;
94+
95+
/// <summary>
96+
/// Creates a new instance of formatting options persistence helper, using given options to predefine the options container.
97+
/// </summary>
98+
/// <param name="propertiesContainer">Properties container to load from and save to.</param>
99+
/// <param name="initialContainer">Initial (empty) instance of formatting options container.</param>
100+
public CSharpFormattingOptionsPersistence(Properties propertiesContainer, CSharpFormattingOptionsContainer initialContainer)
101+
{
102+
if (propertiesContainer == null)
103+
throw new ArgumentNullException("propertiesContainer");
104+
if (initialContainer == null)
105+
throw new ArgumentNullException("initialContainer");
106+
107+
this.propertiesContainer = propertiesContainer;
108+
optionsContainer = initialContainer;
109+
}
110+
111+
public CSharpFormattingOptionsContainer OptionsContainer
112+
{
113+
get {
114+
return optionsContainer;
115+
}
116+
}
117+
118+
/// <summary>
119+
/// Loads formatting settings from properties container.
120+
/// </summary>
121+
public void Load()
122+
{
123+
optionsContainer.Load(propertiesContainer);
124+
}
125+
126+
/// <summary>
127+
/// Saves formatting settings to properties container.
128+
/// </summary>
129+
/// <returns><c>True</c> if successful, <c>false</c> otherwise</returns>
130+
public bool Save()
131+
{
132+
optionsContainer.Save(propertiesContainer);
133+
return true;
134+
}
135+
}
136+
}

0 commit comments

Comments
 (0)