Skip to content

Commit f7cb3ac

Browse files
committed
Add support for allowing empty lines in first dim\comment blocks. Closes #3314:
1 parent 029eb5b commit f7cb3ac

File tree

10 files changed

+243
-15
lines changed

10 files changed

+243
-15
lines changed

Rubberduck.Core/UI/Settings/IndenterSettings.xaml

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2-
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3-
xmlns:converters="clr-namespace:Rubberduck.UI.Settings.Converters"
4-
xmlns:controls="clr-namespace:Rubberduck.UI.Controls"
5-
xmlns:core="clr-namespace:System;assembly=mscorlib"
6-
xmlns:smartIndenter="clr-namespace:Rubberduck.SmartIndenter;assembly=Rubberduck.SmartIndenter"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
4+
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
5+
xmlns:converters="clr-namespace:Rubberduck.UI.Settings.Converters"
6+
xmlns:controls="clr-namespace:Rubberduck.UI.Controls"
7+
xmlns:core="clr-namespace:System;assembly=mscorlib"
8+
xmlns:smartIndenter="clr-namespace:Rubberduck.SmartIndenter;assembly=Rubberduck.SmartIndenter"
9+
xmlns:avalonedit="http://icsharpcode.net/sharpdevelop/avalonedit"
710
x:Class="Rubberduck.UI.Settings.IndenterSettings">
811
<UserControl.Resources>
912
<converters:EndOfLineCommentStyleToVisibilityConverter x:Key="EndOfLineCommentStyleToVisibility"/>
@@ -112,6 +115,16 @@
112115
</AccessText.Text>
113116
</AccessText>
114117
</CheckBox>
118+
<CheckBox Margin="25,0,0,5"
119+
HorizontalAlignment="Left"
120+
IsEnabled="{Binding ElementName=IndentProcedureCheckBox,Path=IsChecked}"
121+
IsChecked="{Binding IgnoreEmptyLinesInFirstBlocks,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
122+
<AccessText TextWrapping="WrapWithOverflow">
123+
<AccessText.Text>
124+
<Resx ResxName="Rubberduck.Resources.RubberduckUI" Key="IndenterSettings_IgnoreEmptyLinesInFirstBlocks"/>
125+
</AccessText.Text>
126+
</AccessText>
127+
</CheckBox>
115128
<CheckBox Margin="5,0,0,5"
116129
HorizontalAlignment="Left"
117130
IsChecked="{Binding IndentEnumTypeAsProcedure,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">

Rubberduck.Core/UI/Settings/IndenterSettingsViewModel.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ public IndenterSettingsViewModel(Configuration config)
3131
_indentEntireProcedureBody = config.UserSettings.IndenterSettings.IndentEntireProcedureBody;
3232
_indentFirstCommentBlock = config.UserSettings.IndenterSettings.IndentFirstCommentBlock;
3333
_indentFirstDeclarationBlock = config.UserSettings.IndenterSettings.IndentFirstDeclarationBlock;
34+
_ignoreEmptyLinesInFirstBlocks = config.UserSettings.IndenterSettings.IgnoreEmptyLinesInFirstBlocks;
3435
_indentSpaces = config.UserSettings.IndenterSettings.IndentSpaces;
3536
_spaceProcedures = config.UserSettings.IndenterSettings.VerticallySpaceProcedures;
3637
_procedureSpacing = config.UserSettings.IndenterSettings.LinesBetweenProcedures;
@@ -319,6 +320,20 @@ public bool IndentFirstDeclarationBlock
319320
}
320321
}
321322

323+
private bool _ignoreEmptyLinesInFirstBlocks;
324+
public bool IgnoreEmptyLinesInFirstBlocks
325+
{
326+
get => _ignoreEmptyLinesInFirstBlocks;
327+
set
328+
{
329+
if (_ignoreEmptyLinesInFirstBlocks != value)
330+
{
331+
_ignoreEmptyLinesInFirstBlocks = value;
332+
OnPropertyChanged();
333+
}
334+
}
335+
}
336+
322337
private int _indentSpaces;
323338
public int IndentSpaces
324339
{
@@ -361,6 +376,18 @@ public int LinesBetweenProcedures
361376
}
362377
}
363378

379+
public string PreviewSampleCode
380+
{
381+
get
382+
{
383+
var indenter = new Indenter(null, GetCurrentSettings);
384+
385+
var lines = RubberduckUI.IndenterSettings_PreviewCode.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
386+
lines = indenter.Indent(lines).ToArray();
387+
return string.Join(Environment.NewLine, lines);
388+
}
389+
}
390+
364391
private IIndenterSettings GetCurrentSettings()
365392
{
366393
return new SmartIndenter.IndenterSettings(false)
@@ -383,6 +410,7 @@ private IIndenterSettings GetCurrentSettings()
383410
IndentEntireProcedureBody = IndentEntireProcedureBody,
384411
IndentFirstCommentBlock = IndentFirstCommentBlock,
385412
IndentFirstDeclarationBlock = IndentFirstDeclarationBlock,
413+
IgnoreEmptyLinesInFirstBlocks = IgnoreEmptyLinesInFirstBlocks,
386414
IndentSpaces = IndentSpaces,
387415
VerticallySpaceProcedures = VerticallySpaceProcedures,
388416
LinesBetweenProcedures = LinesBetweenProcedures
@@ -409,8 +437,9 @@ public void UpdateConfig(Configuration config)
409437
config.UserSettings.IndenterSettings.IndentEnumTypeAsProcedure = IndentEnumTypeAsProcedure;
410438
config.UserSettings.IndenterSettings.IndentCompilerDirectives = IndentCompilerDirectives;
411439
config.UserSettings.IndenterSettings.IndentEntireProcedureBody = IndentEntireProcedureBody;
412-
config.UserSettings.IndenterSettings.IndentFirstCommentBlock = IndentFirstCommentBlock;
440+
config.UserSettings.IndenterSettings.IndentFirstCommentBlock = IndentFirstCommentBlock;
413441
config.UserSettings.IndenterSettings.IndentFirstDeclarationBlock = IndentFirstDeclarationBlock;
442+
config.UserSettings.IndenterSettings.IgnoreEmptyLinesInFirstBlocks = IgnoreEmptyLinesInFirstBlocks;
414443
config.UserSettings.IndenterSettings.IndentSpaces = IndentSpaces;
415444
config.UserSettings.IndenterSettings.VerticallySpaceProcedures = VerticallySpaceProcedures;
416445
config.UserSettings.IndenterSettings.LinesBetweenProcedures = LinesBetweenProcedures;
@@ -441,6 +470,7 @@ private void TransferSettingsToView(IIndenterSettings toLoad)
441470
IndentEntireProcedureBody = toLoad.IndentEntireProcedureBody;
442471
IndentFirstCommentBlock = toLoad.IndentFirstCommentBlock;
443472
IndentFirstDeclarationBlock = toLoad.IndentFirstDeclarationBlock;
473+
IgnoreEmptyLinesInFirstBlocks = toLoad.IgnoreEmptyLinesInFirstBlocks;
444474
IndentSpaces = toLoad.IndentSpaces;
445475
VerticallySpaceProcedures = toLoad.VerticallySpaceProcedures;
446476
LinesBetweenProcedures = toLoad.LinesBetweenProcedures;

Rubberduck.Resources/RubberduckUI.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/RubberduckUI.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,4 +1297,7 @@ NOTE: Restart is required for the setting to take effect.</value>
12971297
<data name="GroupingStyle_ByCategory" xml:space="preserve">
12981298
<value>By category</value>
12991299
</data>
1300+
<data name="IndenterSettings_IgnoreEmptyLinesInFirstBlocks" xml:space="preserve">
1301+
<value>Ignore empty lines when locating first comment and declaration blocks</value>
1302+
</data>
13001303
</root>

Rubberduck.SmartIndenter/IIndenter.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using System.Collections.Generic;
2-
using Rubberduck.VBEditor;
32
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
43

54
namespace Rubberduck.SmartIndenter

Rubberduck.SmartIndenter/IIndenterSettings.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,10 @@
33
public interface IIndenterSettings
44
{
55
bool IndentEntireProcedureBody { get; set; }
6-
bool IndentFirstCommentBlock { get; set; }
76
bool IndentEnumTypeAsProcedure { get; set; }
7+
bool IndentFirstCommentBlock { get; set; }
88
bool IndentFirstDeclarationBlock { get; set; }
9+
bool IgnoreEmptyLinesInFirstBlocks { get; set; }
910
bool AlignCommentsWithCode { get; set; }
1011
bool AlignContinuations { get; set; }
1112
bool IgnoreOperatorsInContinuations { get; set; }

Rubberduck.SmartIndenter/Indenter.cs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,9 +150,9 @@ private void Indent(IVBComponent component, Selection selection)
150150
}
151151
}
152152

153-
private IEnumerable<LogicalCodeLine> BuildLogicalCodeLines(IEnumerable<string> lines)
153+
private IEnumerable<LogicalCodeLine> BuildLogicalCodeLines(IEnumerable<string> lines, out IIndenterSettings settings)
154154
{
155-
var settings = _settings.Invoke();
155+
settings = _settings.Invoke();
156156
var logical = new List<LogicalCodeLine>();
157157
LogicalCodeLine current = null;
158158
AbsoluteCodeLine previous = null;
@@ -203,7 +203,7 @@ public IEnumerable<string> Indent(IEnumerable<string> codeLines, bool forceTrail
203203

204204
private IEnumerable<string> Indent(IEnumerable<string> codeLines, bool forceTrailingNewLines, bool procedure)
205205
{
206-
var logical = BuildLogicalCodeLines(codeLines).ToList();
206+
var logical = BuildLogicalCodeLines(codeLines, out var settings).ToList();
207207
var indents = 0;
208208
var start = false;
209209
var enumStart = false;
@@ -237,7 +237,10 @@ private IEnumerable<string> Indent(IEnumerable<string> codeLines, bool forceTrai
237237
line.AtProcedureStart = start;
238238
line.IndentationLevel = indents - line.Outdents;
239239
indents += line.NextLineIndents;
240-
start = line.IsProcedureStart || (line.AtProcedureStart && line.IsDeclaration) || (line.AtProcedureStart && line.IsCommentBlock);
240+
start = line.IsProcedureStart ||
241+
line.AtProcedureStart && line.IsDeclaration ||
242+
line.AtProcedureStart && line.IsCommentBlock ||
243+
settings.IgnoreEmptyLinesInFirstBlocks && line.AtProcedureStart && line.IsEmpty;
241244
inEnumType = line.IsEnumOrTypeStart;
242245
enumStart = inEnumType;
243246
}

Rubberduck.SmartIndenter/IndenterSettings.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@ public class IndenterSettings : IIndenterSettings, IEquatable<IndenterSettings>
1414
public const int MaximumVerticalSpacing = 2;
1515

1616
public virtual bool IndentEntireProcedureBody { get; set; }
17-
public virtual bool IndentFirstCommentBlock { get; set; }
1817
public virtual bool IndentEnumTypeAsProcedure { get; set; }
18+
public virtual bool IndentFirstCommentBlock { get; set; }
1919
public virtual bool IndentFirstDeclarationBlock { get; set; }
20+
public virtual bool IgnoreEmptyLinesInFirstBlocks { get; set; }
2021
public virtual bool AlignCommentsWithCode { get; set; }
2122
public virtual bool AlignContinuations { get; set; }
2223
public virtual bool IgnoreOperatorsInContinuations { get; set; }
@@ -146,9 +147,10 @@ public IndenterSettings(bool skipRegistry)
146147
// Mocking requires these to be virtual.
147148
// ReSharper disable DoNotCallOverridableMethodsInConstructor
148149
IndentEntireProcedureBody = true;
149-
IndentFirstCommentBlock = true;
150150
IndentEnumTypeAsProcedure = false;
151+
IndentFirstCommentBlock = true;
151152
IndentFirstDeclarationBlock = true;
153+
IgnoreEmptyLinesInFirstBlocks = false;
152154
AlignCommentsWithCode = true;
153155
AlignContinuations = true;
154156
IgnoreOperatorsInContinuations = true;
@@ -176,6 +178,7 @@ public bool Equals(IndenterSettings other)
176178
IndentFirstCommentBlock == other.IndentFirstCommentBlock &&
177179
IndentEnumTypeAsProcedure == other.IndentEnumTypeAsProcedure &&
178180
IndentFirstDeclarationBlock == other.IndentFirstDeclarationBlock &&
181+
IgnoreEmptyLinesInFirstBlocks == other.IgnoreEmptyLinesInFirstBlocks &&
179182
AlignCommentsWithCode == other.AlignCommentsWithCode &&
180183
AlignContinuations == other.AlignContinuations &&
181184
IgnoreOperatorsInContinuations == other.IgnoreOperatorsInContinuations &&
@@ -216,7 +219,7 @@ public void LoadLegacyFromRegistry()
216219
if (reg == null) return;
217220
IndentEntireProcedureBody = GetSmartIndenterBoolean(reg, "IndentProc", IndentEntireProcedureBody);
218221
IndentFirstCommentBlock = GetSmartIndenterBoolean(reg, "IndentFirst", IndentFirstCommentBlock);
219-
IndentFirstDeclarationBlock = GetSmartIndenterBoolean(reg, "IndentDim", IndentFirstDeclarationBlock);
222+
IndentFirstDeclarationBlock = GetSmartIndenterBoolean(reg, "IndentDim", IndentFirstDeclarationBlock);
220223
AlignCommentsWithCode = GetSmartIndenterBoolean(reg, "IndentCmt", AlignCommentsWithCode);
221224
AlignContinuations = GetSmartIndenterBoolean(reg, "AlignContinued", AlignContinuations);
222225
IgnoreOperatorsInContinuations = GetSmartIndenterBoolean(reg, "AlignIgnoreOps", IgnoreOperatorsInContinuations);

RubberduckTests/Settings/IndenterSettingsTests.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ public static Rubberduck.SmartIndenter.IndenterSettings GetMockIndenterSettings(
3030
output.SetupProperty(s => s.IndentEntireProcedureBody);
3131
output.SetupProperty(s => s.IndentFirstCommentBlock);
3232
output.SetupProperty(s => s.IndentFirstDeclarationBlock);
33+
output.SetupProperty(s => s.IgnoreEmptyLinesInFirstBlocks);
3334
output.SetupProperty(s => s.AlignCommentsWithCode);
3435
output.SetupProperty(s => s.AlignContinuations);
3536
output.SetupProperty(s => s.IgnoreOperatorsInContinuations);
@@ -51,6 +52,7 @@ public static Rubberduck.SmartIndenter.IndenterSettings GetMockIndenterSettings(
5152
output.Object.IndentEntireProcedureBody = !nondefault;
5253
output.Object.IndentFirstCommentBlock = !nondefault;
5354
output.Object.IndentFirstDeclarationBlock = !nondefault;
55+
output.Object.IgnoreEmptyLinesInFirstBlocks = nondefault;
5456
output.Object.AlignCommentsWithCode = !nondefault;
5557
output.Object.AlignContinuations = !nondefault;
5658
output.Object.IgnoreOperatorsInContinuations = !nondefault;
@@ -104,13 +106,17 @@ public void SaveConfigWorks()
104106
Assert.AreEqual(config.UserSettings.IndenterSettings.EndOfLineCommentStyle, viewModel.EndOfLineCommentStyle);
105107
Assert.AreEqual(config.UserSettings.IndenterSettings.ForceCompilerDirectivesInColumn1, viewModel.ForceCompilerDirectivesInColumn1);
106108
Assert.AreEqual(config.UserSettings.IndenterSettings.ForceDebugStatementsInColumn1, viewModel.ForceDebugStatementsInColumn1);
109+
Assert.AreEqual(config.UserSettings.IndenterSettings.ForceDebugPrintInColumn1, viewModel.ForceDebugPrintInColumn1);
110+
Assert.AreEqual(config.UserSettings.IndenterSettings.ForceDebugAssertInColumn1, viewModel.ForceDebugAssertInColumn1);
111+
Assert.AreEqual(config.UserSettings.IndenterSettings.ForceStopInColumn1, viewModel.ForceStopInColumn1);
107112
Assert.AreEqual(config.UserSettings.IndenterSettings.IgnoreOperatorsInContinuations, viewModel.IgnoreOperatorsInContinuations);
108113
Assert.AreEqual(config.UserSettings.IndenterSettings.IndentCase, viewModel.IndentCase);
109114
Assert.AreEqual(config.UserSettings.IndenterSettings.IndentEnumTypeAsProcedure, viewModel.IndentEnumTypeAsProcedure);
110115
Assert.AreEqual(config.UserSettings.IndenterSettings.IndentCompilerDirectives, viewModel.IndentCompilerDirectives);
111116
Assert.AreEqual(config.UserSettings.IndenterSettings.IndentEntireProcedureBody, viewModel.IndentEntireProcedureBody);
112117
Assert.AreEqual(config.UserSettings.IndenterSettings.IndentFirstCommentBlock, viewModel.IndentFirstCommentBlock);
113118
Assert.AreEqual(config.UserSettings.IndenterSettings.IndentFirstDeclarationBlock, viewModel.IndentFirstDeclarationBlock);
119+
Assert.AreEqual(config.UserSettings.IndenterSettings.IgnoreEmptyLinesInFirstBlocks, viewModel.IgnoreEmptyLinesInFirstBlocks);
114120
Assert.AreEqual(config.UserSettings.IndenterSettings.IndentSpaces, viewModel.IndentSpaces);
115121
Assert.AreEqual(config.UserSettings.IndenterSettings.VerticallySpaceProcedures, viewModel.VerticallySpaceProcedures);
116122
Assert.AreEqual(config.UserSettings.IndenterSettings.LinesBetweenProcedures, viewModel.LinesBetweenProcedures);
@@ -135,6 +141,9 @@ public void SetDefaultsWorks()
135141
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.EndOfLineCommentColumnSpaceAlignment, viewModel.EndOfLineCommentColumnSpaceAlignment);
136142
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.EndOfLineCommentStyle, viewModel.EndOfLineCommentStyle);
137143
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.ForceCompilerDirectivesInColumn1, viewModel.ForceCompilerDirectivesInColumn1);
144+
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.ForceDebugPrintInColumn1, viewModel.ForceDebugPrintInColumn1);
145+
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.ForceDebugAssertInColumn1, viewModel.ForceDebugAssertInColumn1);
146+
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.ForceStopInColumn1, viewModel.ForceStopInColumn1);
138147
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.ForceDebugStatementsInColumn1, viewModel.ForceDebugStatementsInColumn1);
139148
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.IgnoreOperatorsInContinuations, viewModel.IgnoreOperatorsInContinuations);
140149
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.IndentCase, viewModel.IndentCase);
@@ -143,6 +152,7 @@ public void SetDefaultsWorks()
143152
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.IndentEntireProcedureBody, viewModel.IndentEntireProcedureBody);
144153
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.IndentFirstCommentBlock, viewModel.IndentFirstCommentBlock);
145154
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.IndentFirstDeclarationBlock, viewModel.IndentFirstDeclarationBlock);
155+
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.IgnoreEmptyLinesInFirstBlocks, viewModel.IgnoreEmptyLinesInFirstBlocks);
146156
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.IndentSpaces, viewModel.IndentSpaces);
147157
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.VerticallySpaceProcedures, viewModel.VerticallySpaceProcedures);
148158
Assert.AreEqual(defaultConfig.UserSettings.IndenterSettings.LinesBetweenProcedures, viewModel.LinesBetweenProcedures);

0 commit comments

Comments
 (0)