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

Commit b4eb6be

Browse files
committed
Merge branch 'csformatter'
2 parents 0a0c588 + 8518060 commit b4eb6be

13 files changed

Lines changed: 159 additions & 114 deletions

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
using ICSharpCode.SharpDevelop;
3232
using ICSharpCode.SharpDevelop.Editor;
3333
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
34+
using CSharpBinding.FormattingStrategy;
3435

3536
namespace CSharpBinding.Completion
3637
{
@@ -98,7 +99,8 @@ bool ShowCompletion(ITextEditor editor, char completionChar, bool ctrlSpace)
9899
completionContext.ProjectContent,
99100
completionContext.TypeResolveContextAtCaret
100101
);
101-
cce.FormattingPolicy = FormattingOptionsFactory.CreateSharpDevelop();
102+
var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(completionContext.Compilation.GetProject());
103+
cce.FormattingPolicy = formattingOptions.OptionsContainer.GetEffectiveOptions();
102104
cce.EolMarker = DocumentUtilities.GetLineTerminator(completionContext.Document, currentLocation.Line);
103105

104106
cce.IndentString = editor.Options.IndentationString;

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
using ICSharpCode.NRefactory.Xml;
2929
using ICSharpCode.SharpDevelop.Editor;
3030
using ICSharpCode.SharpDevelop.Editor.CodeCompletion;
31+
using CSharpBinding.FormattingStrategy;
3132

3233
namespace CSharpBinding.Completion
3334
{
@@ -71,7 +72,7 @@ FlowDocumentScrollViewer GenerateHeader()
7172
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
7273
var stringBuilder = new StringBuilder();
7374
var formatter = new ParameterHighlightingOutputFormatter(stringBuilder, highlightedParameterIndex);
74-
ambience.ConvertSymbol(Method, formatter, FormattingOptionsFactory.CreateSharpDevelop());
75+
ambience.ConvertSymbol(Method, formatter, CSharpFormattingOptionsPersistence.GlobalOptions.OptionsContainer.GetEffectiveOptions());
7576

7677
var documentation = XmlDocumentationElement.Get(Method);
7778
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;

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

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,13 +34,10 @@ namespace CSharpBinding.FormattingStrategy
3434
/// </summary>
3535
internal class CSharpFormattingOptionsContainer : INotifyPropertyChanged
3636
{
37-
private const string AutoFormattingOptionName = "AutoFormatting";
38-
3937
CSharpFormattingOptionsContainer parent;
4038
CSharpFormattingOptions cachedOptions;
4139

4240
readonly HashSet<string> activeOptions;
43-
bool? autoFormatting;
4441

4542
public CSharpFormattingOptionsContainer(CSharpFormattingOptionsContainer parent = null)
4643
: this(parent, new HashSet<string>())
@@ -71,34 +68,6 @@ public CSharpFormattingOptionsContainer Parent
7168
}
7269
}
7370

74-
public bool? AutoFormatting
75-
{
76-
get {
77-
return autoFormatting;
78-
}
79-
set {
80-
autoFormatting = value;
81-
OnPropertyChanged("AutoFormatting");
82-
}
83-
}
84-
85-
public bool EffectiveAutoFormatting
86-
{
87-
get {
88-
// Get "effective" option, i.e. walk up all parents to find a defined value
89-
CSharpFormattingOptionsContainer container = this;
90-
do
91-
{
92-
if (container.autoFormatting.HasValue) {
93-
return container.autoFormatting.Value;
94-
}
95-
container = container.parent;
96-
} while (container != null);
97-
98-
return true;
99-
}
100-
}
101-
10271
/// <summary>
10372
/// Resets all container's options to given <see cref="ICSharpCode.NRefactory.CSharp.CSharpFormattingOptions"/> instance.
10473
/// </summary>
@@ -112,7 +81,6 @@ public void Reset(CSharpFormattingOptions options = null)
11281
foreach (var property in typeof(CSharpFormattingOptions).GetProperties()) {
11382
activeOptions.Add(property.Name);
11483
}
115-
autoFormatting = true;
11684
}
11785
OnPropertyChanged(null);
11886
}
@@ -138,7 +106,6 @@ public void CloneFrom(CSharpFormattingOptionsContainer options)
138106
foreach (var activeOption in options.activeOptions)
139107
activeOptions.Add(activeOption);
140108
cachedOptions = options.cachedOptions.Clone();
141-
autoFormatting = options.autoFormatting;
142109
OnPropertyChanged(null);
143110
}
144111

@@ -308,11 +275,6 @@ public void Load(Properties parentProperties)
308275
// Silently ignore loading error, then this property will be "as parent" automatically
309276
}
310277
}
311-
if (formatProperties.Contains(AutoFormattingOptionName)) {
312-
autoFormatting = formatProperties.Get(AutoFormattingOptionName, true);
313-
} else {
314-
autoFormatting = null;
315-
}
316278
}
317279
}
318280

@@ -329,12 +291,6 @@ public void Save(Properties parentProperties)
329291
formatProperties.Set(activeOption, val);
330292
}
331293
}
332-
if (formatProperties.Contains(AutoFormattingOptionName) && !autoFormatting.HasValue) {
333-
// AutoFormatting options was activated previously, remove it now
334-
formatProperties.Remove(AutoFormattingOptionName);
335-
} else {
336-
formatProperties.Set(AutoFormattingOptionName, autoFormatting);
337-
}
338294

339295
parentProperties.SetNestedProperties("CSharpFormatting", formatProperties);
340296
}

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,16 @@ public static void Initialize()
7171
}
7272
}
7373

74+
public static bool AutoFormatting
75+
{
76+
get {
77+
return SD.PropertyService.Get("CSharpBinding.Formatting.AutoFormatting", true);
78+
}
79+
set {
80+
SD.PropertyService.Set("CSharpBinding.Formatting.AutoFormatting", value);
81+
}
82+
}
83+
7484
public static CSharpFormattingOptionsPersistence GlobalOptions
7585
{
7686
get;

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

Lines changed: 106 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ bool NeedCurlyBracket(string text)
155155
if ((inString && !verbatim) || inChar)
156156
++i; // skip next character
157157
break;
158-
}
158+
}
159159
}
160160
return curlyCounter > 0;
161161
}
@@ -269,16 +269,43 @@ bool NeedEndregion(IDocument document)
269269

270270
public override void FormatLines(ITextEditor textArea)
271271
{
272+
// Format current selection or whole document
273+
int formattedTextOffset = 0;
274+
int formattedTextLength = textArea.Document.TextLength;
275+
if (textArea.SelectionLength != 0) {
276+
formattedTextOffset = textArea.SelectionStart;
277+
formattedTextLength = textArea.SelectionLength;
278+
}
279+
FormatCode(textArea, formattedTextOffset, formattedTextLength, false);
280+
}
281+
282+
/// <summary>
283+
/// Formats a code section according to currently effective formatting settings.
284+
/// </summary>
285+
/// <param name="textArea">Text editor instance to format code in.</param>
286+
/// <param name="offset">Start offset of formatted code.</param>
287+
/// <param name="length">Length of formatted code.</param>
288+
/// <param name="respectAutoFormattingSetting">
289+
/// Set to <c>true</c> to perform formatting only if auto-formatting setting is active.
290+
/// If <c>false</c>, formatting will be performed in any case.
291+
/// </param>
292+
/// <returns><c>True</c>, if code has been formatted, <c>false</c> if auto-formatting is currently forbidden.</returns>
293+
private bool FormatCode(ITextEditor textArea, int offset, int length, bool respectAutoFormattingSetting)
294+
{
295+
if ((offset > textArea.Document.TextLength) || ((offset + length) > textArea.Document.TextLength))
296+
return false;
297+
if (respectAutoFormattingSetting && !CSharpFormattingOptionsPersistence.AutoFormatting)
298+
return false;
299+
272300
using (textArea.Document.OpenUndoGroup()) {
273-
// In any other case: Simply format selection or whole document
274301
var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(SD.ProjectService.CurrentProject);
275-
int formattedTextOffset = 0;
276-
int formattedTextLength = textArea.Document.TextLength;
277-
if (textArea.SelectionLength != 0) {
278-
formattedTextOffset = textArea.SelectionStart;
279-
formattedTextLength = textArea.SelectionLength;
302+
try {
303+
CSharpFormatterHelper.Format(textArea, offset, length, formattingOptions.OptionsContainer);
304+
} catch (Exception) {
305+
// Exceptions in formatting might happen if code contains syntax errors, we have to catch them
306+
return false;
280307
}
281-
CSharpFormatterHelper.Format(textArea, formattedTextOffset, formattedTextLength, formattingOptions.OptionsContainer);
308+
return true;
282309
}
283310
}
284311

@@ -289,6 +316,24 @@ public override void FormatLines(ITextEditor textArea)
289316
}
290317
}
291318

319+
bool FormatStatement(ITextEditor textArea, int cursorOffset, int formattingStartOffset)
320+
{
321+
var line = textArea.Document.GetLineByOffset(formattingStartOffset);
322+
int lineOffset = line.Offset;
323+
// Walk up the lines until we arrive at previous statement, block, comment or preprocessor directive
324+
while (line.PreviousLine != null) {
325+
line = line.PreviousLine;
326+
string lineText = textArea.Document.GetText(line.Offset, line.Length);
327+
if (IsLineEndOfStatement(lineText)) {
328+
// Previous line is another statement, don't format it
329+
break;
330+
}
331+
lineOffset = line.Offset;
332+
}
333+
334+
return FormatCode(textArea, lineOffset, cursorOffset - lineOffset, true);
335+
}
336+
292337
void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char ch)
293338
{
294339
IDocumentLine curLine = textArea.Document.GetLineByNumber(lineNr);
@@ -375,12 +420,29 @@ void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char
375420
case ':':
376421
case ')':
377422
case ']':
378-
case '}':
379423
case '{':
380424
//if (textArea.Document.TextEditorProperties.IndentStyle == IndentStyle.Smart) {
381425
IndentLine(textArea, curLine);
382426
//}
383427
break;
428+
case '}':
429+
// Try to get corresponding block beginning brace
430+
var bracketSearchResult = textArea.Language.BracketSearcher.SearchBracket(textArea.Document, cursorOffset);
431+
if (bracketSearchResult != null) {
432+
// Format the block
433+
if (!FormatStatement(textArea, cursorOffset, bracketSearchResult.OpeningBracketOffset)) {
434+
// No auto-formatting seems to be active, at least indent the line
435+
IndentLine(textArea, curLine);
436+
}
437+
}
438+
break;
439+
case ';':
440+
// Format this line
441+
if (!FormatStatement(textArea, cursorOffset, cursorOffset)) {
442+
// No auto-formatting seems to be active, at least indent the line
443+
IndentLine(textArea, curLine);
444+
}
445+
break;
384446
case '\n':
385447
string lineAboveText = lineAbove == null ? "" : textArea.Document.GetText(lineAbove);
386448
// curLine might have some text which should be added to indentation
@@ -445,7 +507,41 @@ void FormatLineInternal(ITextEditor textArea, int lineNr, int cursorOffset, char
445507
}
446508
}
447509
return;
510+
}
511+
}
512+
513+
bool IsLineEndOfStatement(string lineText)
514+
{
515+
string normalizedLine = null;
516+
517+
// Look if there is a comment at the end of line
518+
int indexOfSingleLineComment = lineText.LastIndexOf("//");
519+
if (indexOfSingleLineComment > -1) {
520+
normalizedLine = lineText.Substring(0, indexOfSingleLineComment);
521+
} else {
522+
normalizedLine = lineText;
448523
}
524+
525+
normalizedLine = normalizedLine.Trim(' ', '\t');
526+
527+
if (normalizedLine.EndsWith("*/")) {
528+
int indexOfMultiLineCommentStart = normalizedLine.LastIndexOf("/*");
529+
if (indexOfMultiLineCommentStart > -1) {
530+
normalizedLine = normalizedLine.Substring(0, indexOfMultiLineCommentStart);
531+
} else {
532+
// Seems to be a multiline comment (no comment start on this line)
533+
return true;
534+
}
535+
}
536+
537+
// Usual statement endings
538+
if (normalizedLine.StartsWith("#")
539+
|| normalizedLine.EndsWith(";")
540+
|| normalizedLine.EndsWith("{")
541+
|| normalizedLine.EndsWith("}"))
542+
return true;
543+
544+
return false;
449545
}
450546

451547
/// <summary>
@@ -554,7 +650,7 @@ static int GetStartType(IDocument document, int linestart, int offset)
554650
if ((inString && !verbatim) || inChar)
555651
++i; // skip next character
556652
break;
557-
}
653+
}
558654
}
559655
return (inString || inChar) ? 2 : 0;
560656
}

src/AddIns/BackendBindings/CSharpBinding/Project/Src/FormsDesigner/CSharpDesignerGenerator.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
using ICSharpCode.SharpDevelop.Editor;
3636
using ICSharpCode.SharpDevelop.Project;
3737
using Microsoft.CSharp;
38+
using CSharpBinding.FormattingStrategy;
3839
using CSharpBinding.Parser;
3940
using CSharpBinding.Refactoring;
4041

@@ -154,7 +155,8 @@ DocumentScript GetScript(string fileName)
154155

155156
IDocument document = context.GetDocument(fileNameObj);
156157
var ctx = SDRefactoringContext.Create(fileNameObj, document);
157-
script = new DocumentScript(document, FormattingOptionsFactory.CreateSharpDevelop(), new TextEditorOptions());
158+
var formattingOptions = CSharpFormattingOptionsPersistence.GetProjectOptions(compilation.GetProject());
159+
script = new DocumentScript(document, formattingOptions.OptionsContainer.GetEffectiveOptions(), new TextEditorOptions());
158160
scripts.Add(fileNameObj, script);
159161
return script;
160162
}

src/AddIns/BackendBindings/CSharpBinding/Project/Src/OptionPanels/CSharpFormattingEditor.xaml

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -297,24 +297,17 @@
297297
</UserControl.Resources>
298298

299299
<DockPanel>
300-
<StackPanel DockPanel.Dock="Top" Orientation="Vertical">
301-
<CheckBox
302-
Name="autoFormattingCheckBox"
303-
Content="{core:Localize CSharpBinding.Formatting.AutoFormat}"
304-
IsThreeState="True" IsChecked="{Binding AutoFormatting}"
305-
Margin="0,0,0,10"
306-
Visibility="Collapsed"/>
307-
<Grid
308-
Visibility="{Binding Path=AllowPresets, Converter={StaticResource boolToVisibilityConverter}}">
309-
<Grid.ColumnDefinitions>
310-
<ColumnDefinition Width="Auto" />
311-
<ColumnDefinition Width="*" />
312-
</Grid.ColumnDefinitions>
313-
314-
<Button Grid.Column="0" Content="{core:Localize CSharpBinding.Formatting.ResetTo}" Click="ResetButton_Click" />
315-
<ComboBox Name="presetComboBox" Grid.Column="1" Margin="3,0,0,0" ItemsSource="{Binding Presets}" />
316-
</Grid>
317-
</StackPanel>
300+
<Grid
301+
Visibility="{Binding Path=AllowPresets, Converter={StaticResource boolToVisibilityConverter}}"
302+
DockPanel.Dock="Top">
303+
<Grid.ColumnDefinitions>
304+
<ColumnDefinition Width="Auto" />
305+
<ColumnDefinition Width="*" />
306+
</Grid.ColumnDefinitions>
307+
308+
<Button Grid.Column="0" Content="{core:Localize CSharpBinding.Formatting.ResetTo}" Click="ResetButton_Click" />
309+
<ComboBox Name="presetComboBox" Grid.Column="1" Margin="3,0,0,0" ItemsSource="{Binding Presets}" />
310+
</Grid>
318311

319312
<sd:RestrictDesiredSize Margin="0,4,0,0">
320313
<ScrollViewer VerticalScrollBarVisibility="Auto">

0 commit comments

Comments
 (0)