Skip to content

Commit ecd5913

Browse files
authored
Merge branch 'next' into next
2 parents d73dd76 + 0dae613 commit ecd5913

File tree

55 files changed

+1992
-337
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1992
-337
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ If you like this project and would like to thank its contributors, you are welco
3737

3838
Rubberduck is a COM add-in for the VBA IDE (VBE).
3939

40-
Copyright (C) 2014-2018 Mathieu Guindon & Christopher McClellan
40+
Copyright (C) 2014-2018 Rubberduck project contributors
4141

4242
This program is free software: you can redistribute it and/or modify
4343
it under the terms of the GNU General Public License as published by

Rubberduck.CodeAnalysis/Inspections/Concrete/MultilineParameterInspection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
3030
.Select(context => new QualifiedContextInspectionResult(this,
3131
string.Format(context.Context.GetSelection().LineCount > 3
3232
? RubberduckUI.EasterEgg_Continuator
33-
: Resources.Inspections.InspectionResults.MultilineParameterInspection, ((VBAParser.ArgContext)context.Context).unrestrictedIdentifier().ToString()),
33+
: Resources.Inspections.InspectionResults.MultilineParameterInspection, ((VBAParser.ArgContext)context.Context).unrestrictedIdentifier().GetText()),
3434
context));
3535
}
3636

Rubberduck.CodeAnalysis/QuickFixes/IntroduceLocalVariableQuickFix.cs

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
using System;
2+
using System.Text.RegularExpressions;
23
using Rubberduck.Inspections.Abstract;
34
using Rubberduck.Inspections.Concrete;
5+
using Rubberduck.Parsing;
6+
using Rubberduck.Parsing.Grammar;
47
using Rubberduck.Parsing.Inspections.Abstract;
58
using Rubberduck.Parsing.VBA;
69

@@ -22,8 +25,60 @@ public IntroduceLocalVariableQuickFix(RubberduckParserState state)
2225

2326
public override void Fix(IInspectionResult result)
2427
{
25-
var instruction = $"{Environment.NewLine}Dim {result.Target.IdentifierName} As Variant{Environment.NewLine}";
26-
_state.GetRewriter(result.Target).InsertBefore(result.Target.Context.Start.TokenIndex, instruction);
28+
var identifierContext = result.Target.Context;
29+
var enclosingStatmentContext = identifierContext.GetAncestor<VBAParser.BlockStmtContext>();
30+
var instruction = IdentifierDeclarationText(result.Target.IdentifierName, EndOfStatementText(enclosingStatmentContext), FrontPadding(enclosingStatmentContext));
31+
_state.GetRewriter(result.Target).InsertBefore(enclosingStatmentContext.Start.TokenIndex, instruction);
32+
}
33+
34+
private string EndOfStatementText(VBAParser.BlockStmtContext context)
35+
{
36+
if (!context.TryGetPrecedingContext<VBAParser.IndividualNonEOFEndOfStatementContext>(out var individualEndOfStmtContext))
37+
{
38+
return Environment.NewLine;
39+
}
40+
41+
var endOfLine = individualEndOfStmtContext.endOfLine();
42+
43+
if (endOfLine?.commentOrAnnotation() == null)
44+
{
45+
return individualEndOfStmtContext.GetText();
46+
}
47+
48+
//There is a comment inside the preceding endOfLine, which we do not want to duplicate.
49+
var whitespaceContext = individualEndOfStmtContext.whiteSpace(0);
50+
return Environment.NewLine + (whitespaceContext?.GetText() ?? string.Empty);
51+
}
52+
53+
private string FrontPadding(VBAParser.BlockStmtContext context)
54+
{
55+
var statementLabelContext = context.statementLabelDefinition();
56+
if (statementLabelContext == null)
57+
{
58+
return string.Empty;
59+
}
60+
61+
var statementLabelTextAsWhitespace = ReplaceNonWhitespaceWithSpace(statementLabelContext.GetText());
62+
var whitespaceContext = context.whiteSpace();
63+
return statementLabelTextAsWhitespace + (whitespaceContext?.GetText() ?? string.Empty);
64+
}
65+
66+
private string ReplaceNonWhitespaceWithSpace(string input)
67+
{
68+
if (input == null || input.Equals(string.Empty))
69+
{
70+
return string.Empty;
71+
}
72+
73+
var pattern = @"[^\r\n\t ]";
74+
var replacement = " ";
75+
var regex = new Regex(pattern);
76+
return regex.Replace(input, replacement);
77+
}
78+
79+
private string IdentifierDeclarationText(string identifierName, string endOfStatementText, string prefix)
80+
{
81+
return $"{prefix}Dim {identifierName} As Variant{endOfStatementText}";
2782
}
2883

2984
public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.IntroduceLocalVariableQuickFix;

Rubberduck.Core/Rubberduck.Core.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,7 @@
536536
<Compile Include="UnitTesting\IFakes.cs" />
537537
<Compile Include="UnitTesting\ReturnTypeConverter.cs" />
538538
<Compile Include="UnitTesting\PermissiveObjectComparer.cs" />
539+
<Compile Include="UnitTesting\TestCategory.cs" />
539540
<Compile Include="VersionCheck\IVersionCheck.cs" />
540541
<Compile Include="UI\Command\MenuItems\CommandBars\AppCommandBarBase.cs" />
541542
<Compile Include="UI\Command\MenuItems\CommandBars\ContextSelectionLabelMenuItem.cs" />

Rubberduck.Core/UI/About/AboutControl.xaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,7 @@
167167
xml:space="preserve">JetBrains ReSharper Community Team
168168
Code Review Stack Exchange
169169
Stack Overflow
170+
Digital Ocean Hacktoberfest
170171
</TextBlock>
171172

172173
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.About.AboutUI, Key=AboutWindow_ContributorsHeader}"
@@ -176,32 +177,40 @@ Stack Overflow
176177
xml:space="preserve">Abraham Hosch
177178
Andrew Jackson
178179
Andrew Zschetzsche
180+
Andrew Mansell
179181
Andrin Meier
182+
Anna Velcheva
180183
Brandon Barney
181184
Brian Zenger
182185
Bruno Costa
183186
Carlos J. Quintero (MZ-Tools)
184187
Clemens Lieb
185188
@Comintern
189+
Christopher McClellan
186190
@daFreeMan
187191
@Duga SE chat bot
188192
Francis Veilleux-Gaboury
189193
Frank Van Heeswijk
190194
Gareth Leachman
191195
@Heslacher
196+
Imh0t3b
192197
INOPIAE
198+
Ipshita Chatterjee
193199
@IvenBach
194200
Jeroen Vannevel
201+
Mathieu Guindon
195202
Max Dörner
196203
Michal Krzych
197204
@mjolka
205+
Nelson Vides
198206
Philip Wales
199207
Radosław Kapka
200208
Rob Bovey (Smart Indenter)
201209
Ross McLean
202210
Ross Knudsen
203211
Simon Forsberg
204212
Stephen Bullen (Smart Indenter)
213+
@tommy9
205214
Wayne Phillips (vbWatchdog)
206215
</TextBlock>
207216

Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@
269269

270270
<CollectionViewSource x:Key="ResultsByOutcome" Source="{Binding Model.Tests}">
271271
<CollectionViewSource.SortDescriptions>
272-
<componentModel:SortDescription PropertyName="Result.Outcome" />
272+
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.QualifiedModuleName.Name" />
273273
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.MemberName" />
274274
</CollectionViewSource.SortDescriptions>
275275
<CollectionViewSource.GroupDescriptions>
@@ -278,6 +278,19 @@
278278

279279
</CollectionViewSource.GroupDescriptions>
280280
</CollectionViewSource>
281+
282+
<CollectionViewSource x:Key="ResultsByCategory" Source="{Binding Model.Tests}">
283+
<CollectionViewSource.SortDescriptions>
284+
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.QualifiedModuleName.Name" />
285+
<componentModel:SortDescription PropertyName="Declaration.QualifiedName.MemberName" />
286+
</CollectionViewSource.SortDescriptions>
287+
<CollectionViewSource.GroupDescriptions>
288+
289+
<PropertyGroupDescription PropertyName="Category.Name" />
290+
291+
</CollectionViewSource.GroupDescriptions>
292+
</CollectionViewSource>
293+
281294
<SolidColorBrush x:Key="ToolBarToggleButtonVerticalBackground" Color="#FFEEF5FD"/>
282295
<SolidColorBrush x:Key="ToolBarButtonHover" Color="#210080FF"/>
283296
<SolidColorBrush x:Key="ToolBarGripper" Color="#FF6D6D6D"/>
@@ -504,6 +517,11 @@
504517
<Image Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/flask--arrow.png" />
505518
</MenuItem.Icon>
506519
</MenuItem>
520+
<MenuItem Command="{Binding RunSelectedCategoryTestsCommand}" Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer ,Key=TestExplorer_RunSelectedCategoryTests}" >
521+
<MenuItem.Icon>
522+
<Image Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/flask--arrow.png" />
523+
</MenuItem.Icon>
524+
</MenuItem>
507525
<MenuItem Command="{Binding RunInconclusiveTestsCommand}" Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_RunInconclusiveTests}" >
508526
<MenuItem.Icon>
509527
<Image Source="pack://application:,,,/Rubberduck.Resources;component/Icons/Fugue/flask--exclamation.png" />
@@ -572,6 +590,15 @@
572590
Command="{Binding SetLocationGroupingCommand}"
573591
CommandParameter="{Binding ElementName=GroupByLocation, Path=IsChecked}"
574592
controls:MenuItemGroup.GroupName="TestExplorer_GroupingStyle" />
593+
<MenuItem x:Name="GroupByCategory"
594+
Style="{DynamicResource MenuItemStyle}"
595+
VerticalAlignment="Center"
596+
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=GroupingStyle_ByCategory}"
597+
IsChecked="{Binding GroupByCategory, UpdateSourceTrigger=PropertyChanged}"
598+
IsCheckable="True"
599+
Command="{Binding SetCategoryGroupingCommand}"
600+
CommandParameter="{Binding ElementName=GroupByCategory, Path=IsChecked}"
601+
controls:MenuItemGroup.GroupName="TestExplorer_GroupingStyle" />
575602
</MenuItem>
576603
</Menu>
577604

@@ -615,6 +642,7 @@
615642
</DataGridTemplateColumn>
616643
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}" />
617644
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.IdentifierName}" />
645+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_CategoryName}" Binding="{Binding Category.Name}" />
618646
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
619647
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
620648
</DataGrid.Columns>
@@ -633,6 +661,26 @@
633661
</DataGridTemplateColumn>
634662
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}" />
635663
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.QualifiedName.MemberName}" />
664+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_CategoryName}" Binding="{Binding Category.Name}" />
665+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
666+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
667+
</DataGrid.Columns>
668+
</controls:GroupingGrid>
669+
<controls:GroupingGrid ItemsSource="{Binding Source={StaticResource ResultsByCategory}}"
670+
SelectedItem="{Binding SelectedTest}"
671+
ShowGroupingItemCount="True"
672+
Visibility="{Binding IsChecked, ElementName=GroupByCategory, Converter={StaticResource BoolToVisibility}}">
673+
<DataGrid.Columns>
674+
<DataGridTemplateColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Outcome}">
675+
<DataGridTemplateColumn.CellTemplate>
676+
<DataTemplate DataType="unitTesting:TestMethod">
677+
<Image Source="{Binding Result.Outcome, Converter={StaticResource OutcomeIconConverter}}" Height="16" />
678+
</DataTemplate>
679+
</DataGridTemplateColumn.CellTemplate>
680+
</DataGridTemplateColumn>
681+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_QualifiedModuleName}" Binding="{Binding Declaration.QualifiedName.QualifiedModuleName}" />
682+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_MethodName}" Binding="{Binding Declaration.QualifiedName.MemberName}" />
683+
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_CategoryName}" Binding="{Binding Category.Name}" />
636684
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Message}" Binding="{Binding Result.Output}" Width="*" />
637685
<DataGridTextColumn Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_Duration}" Binding="{Binding Result.Duration, StringFormat={}{0}ms}" />
638686
</DataGrid.Columns>

Rubberduck.Core/UI/UnitTesting/TestExplorerViewModel.cs

Lines changed: 73 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,43 @@ public TestExplorerViewModel(IVBE vbe,
6060
RunFailedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunFailedTestsCommand, CanExecuteRunFailedTestsCommand);
6161
RunPassedTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunPassedTestsCommand, CanExecuteRunPassedTestsCommand);
6262
RunSelectedTestCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteSelectedTestCommand, CanExecuteSelectedTestCommand);
63+
RunSelectedCategoryTestsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteRunSelectedCategoryTestsCommand, CanExecuteRunSelectedCategoryTestsCommand);
6364

6465
CopyResultsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), ExecuteCopyResultsCommand);
6566

6667
OpenTestSettingsCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), OpenSettings);
6768

6869
SetOutcomeGroupingCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), param =>
6970
{
70-
GroupByOutcome = (bool)param;
71-
GroupByLocation = !(bool)param;
71+
GroupByOutcome = true;
72+
73+
if ((bool)param)
74+
{
75+
GroupByLocation = false;
76+
GroupByCategory = false;
77+
}
7278
});
7379

7480
SetLocationGroupingCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), param =>
7581
{
76-
GroupByLocation = (bool)param;
77-
GroupByOutcome = !(bool)param;
82+
GroupByLocation = true;
83+
84+
if ((bool) param)
85+
{
86+
GroupByOutcome = false;
87+
GroupByCategory = false;
88+
}
89+
});
90+
91+
SetCategoryGroupingCommand = new DelegateCommand(LogManager.GetCurrentClassLogger(), param =>
92+
{
93+
GroupByCategory = true;
94+
95+
if ((bool)param)
96+
{
97+
GroupByOutcome = false;
98+
GroupByLocation = false;
99+
}
78100
});
79101
}
80102

@@ -162,10 +184,28 @@ public bool GroupByLocation
162184
}
163185
}
164186

187+
private bool _groupByCategory;
188+
public bool GroupByCategory
189+
{
190+
get => _groupByCategory;
191+
set
192+
{
193+
if (_groupByCategory == value)
194+
{
195+
return;
196+
}
197+
198+
_groupByCategory = value;
199+
OnPropertyChanged();
200+
}
201+
}
202+
165203
public CommandBase SetOutcomeGroupingCommand { get; }
166204

167205
public CommandBase SetLocationGroupingCommand { get; }
168206

207+
public CommandBase SetCategoryGroupingCommand { get; }
208+
169209
public long TotalDuration { get; private set; }
170210

171211
public RunAllTestsCommand RunAllTestsCommand { get; }
@@ -195,6 +235,8 @@ public bool GroupByLocation
195235

196236
public CommandBase RunSelectedTestCommand { get; }
197237

238+
public CommandBase RunSelectedCategoryTestsCommand { get; }
239+
198240
public CommandBase OpenTestSettingsCommand { get; }
199241

200242
private void OpenSettings(object param)
@@ -382,6 +424,33 @@ private void ExecuteCopyResultsCommand(object parameter)
382424
_clipboard.Flush();
383425
}
384426

427+
private void ExecuteRunSelectedCategoryTestsCommand(object obj)
428+
{
429+
EnsureRubberduckIsReferencedForEarlyBoundTests();
430+
431+
Model.ClearLastRun();
432+
433+
var stopwatch = new Stopwatch();
434+
Model.IsBusy = true;
435+
436+
stopwatch.Start();
437+
_testEngine.Run(Model.Tests.Where(test => test.Category.Equals(SelectedTest.Category)));
438+
stopwatch.Stop();
439+
440+
Model.IsBusy = false;
441+
TotalDuration = stopwatch.ElapsedMilliseconds;
442+
}
443+
444+
private bool CanExecuteRunSelectedCategoryTestsCommand(object obj)
445+
{
446+
if (Model.IsBusy || SelectedItem == null)
447+
{
448+
return false;
449+
}
450+
451+
return ((TestMethod) SelectedItem).Category.Name != string.Empty;
452+
}
453+
385454
//KEEP THIS, AS IT MAKES FOR THE BASIS OF A USEFUL *SUMMARY* REPORT
386455
//private void ExecuteCopyResultsCommand(object parameter)
387456
//{
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
using System;
2+
3+
namespace Rubberduck.UnitTesting
4+
{
5+
public class TestCategory
6+
{
7+
public string Name { get; }
8+
9+
public TestCategory(string name)
10+
{
11+
Name = name ?? throw new ArgumentNullException(nameof(name));
12+
}
13+
14+
public override bool Equals(object obj)
15+
{
16+
if (!(obj is TestCategory category))
17+
{
18+
return false;
19+
}
20+
21+
return Name == category.Name;
22+
}
23+
24+
public override int GetHashCode()
25+
{
26+
return Name.GetHashCode();
27+
}
28+
}
29+
}

0 commit comments

Comments
 (0)