From 74454291114e034c2a245a30059f591055d1f192 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Tue, 29 Dec 2015 02:34:13 -0500 Subject: [PATCH 01/18] code inspection results are displayed without a manual refresh, and running quickfixes reparses and refreshes. --- .../CodeInspections/CodeInspectionsWindow.cs | 4 ++++ .../InspectionResultsViewModel.cs | 24 +++++++++++++++---- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/RetailCoder.VBE/UI/CodeInspections/CodeInspectionsWindow.cs b/RetailCoder.VBE/UI/CodeInspections/CodeInspectionsWindow.cs index aa1c343403..38bd16dd63 100644 --- a/RetailCoder.VBE/UI/CodeInspections/CodeInspectionsWindow.cs +++ b/RetailCoder.VBE/UI/CodeInspections/CodeInspectionsWindow.cs @@ -27,6 +27,10 @@ public InspectionResultsViewModel ViewModel { _viewModel = value; wpfInspectionResultsControl.DataContext = _viewModel; + if (_viewModel != null) + { + _viewModel.RefreshCommand.Execute(null); + } } } } diff --git a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs index 14f263b93e..25a0462329 100644 --- a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs +++ b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs @@ -9,7 +9,7 @@ using Microsoft.Vbe.Interop; using Rubberduck.Common; using Rubberduck.Inspections; -using Rubberduck.Parsing; +using Rubberduck.Parsing.VBA; using Rubberduck.Settings; using Rubberduck.UI.Command; using Rubberduck.VBEditor.Extensions; @@ -18,16 +18,16 @@ namespace Rubberduck.UI.CodeInspections { public class InspectionResultsViewModel : ViewModelBase { - private readonly IRubberduckParser _parser; + private readonly RubberduckParserState _state; private readonly IInspector _inspector; private readonly VBE _vbe; private readonly INavigateCommand _navigateCommand; private readonly IClipboardWriter _clipboard; private readonly IGeneralConfigService _configService; - public InspectionResultsViewModel(IRubberduckParser parser, IInspector inspector, VBE vbe, INavigateCommand navigateCommand, IClipboardWriter clipboard, IGeneralConfigService configService) + public InspectionResultsViewModel(RubberduckParserState state, IInspector inspector, VBE vbe, INavigateCommand navigateCommand, IClipboardWriter clipboard, IGeneralConfigService configService) { - _parser = parser; + _state = state; _inspector = inspector; _vbe = vbe; _navigateCommand = navigateCommand; @@ -155,11 +155,25 @@ private async void ExecuteRefreshCommandAsync(object parameter) CanRefresh = false; // if commands' CanExecute worked as expected, this junk wouldn't be needed IsBusy = true; - var results = await _inspector.FindIssuesAsync(_parser.State, CancellationToken.None); + + _state.StateChanged += _state_StateChanged; + _state.OnParseRequested(); + } + + private async void _state_StateChanged(object sender, ParserStateEventArgs e) + { + if (e.State != ParserState.Ready) + { + return; + } + + var results = await _inspector.FindIssuesAsync(_state, CancellationToken.None); Results = new ObservableCollection(results); CanRefresh = true; IsBusy = false; SelectedItem = null; + + _state.StateChanged -= _state_StateChanged; } private void ExecuteQuickFixes(IEnumerable quickFixes) From 2db56c06cdfc833005bc51a704871d73bc7affe0 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Tue, 29 Dec 2015 02:39:20 -0500 Subject: [PATCH 02/18] added ParserState to ParseProgressEventArgs to ModuleStateChanged can report component state --- Rubberduck.Parsing/IParseResultProvider.cs | 12 ++++++++---- Rubberduck.Parsing/VBA/RubberduckParserState.cs | 6 +++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Rubberduck.Parsing/IParseResultProvider.cs b/Rubberduck.Parsing/IParseResultProvider.cs index 9a273ff93d..b9261cc246 100644 --- a/Rubberduck.Parsing/IParseResultProvider.cs +++ b/Rubberduck.Parsing/IParseResultProvider.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.Vbe.Interop; +using Rubberduck.Parsing.VBA; namespace Rubberduck.Parsing { @@ -32,13 +33,16 @@ public ResolutionProgressEventArgs(VBComponent component, decimal percentProgres public class ParseProgressEventArgs : EventArgs { - private readonly VBComponent _result; + private readonly VBComponent _component; + private readonly ParserState _state; - public ParseProgressEventArgs(VBComponent result) + public ParseProgressEventArgs(VBComponent component, ParserState state) { - _result = result; + _component = component; + _state = state; } - public VBComponent Component { get { return _result; } } + public VBComponent Component { get { return _component; } } + public ParserState State { get { return _state; } } } } diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs index 8895a0b40a..25e08451da 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs @@ -62,12 +62,12 @@ private void OnStateChanged(ParserState state) private readonly object _lock = new object(); public event EventHandler ModuleStateChanged; - private void OnModuleStateChanged(VBComponent component) + private void OnModuleStateChanged(VBComponent component, ParserState state) { var handler = ModuleStateChanged; if (handler != null) { - var args = new ParseProgressEventArgs(component); + var args = new ParseProgressEventArgs(component, state); handler.Invoke(this, args); } } @@ -80,7 +80,7 @@ public void SetModuleState(VBComponent component, ParserState state, SyntaxError // prevent multiple threads from changing state simultaneously: lock(_lock) { - OnModuleStateChanged(component); + OnModuleStateChanged(component, state); Status = EvaluateParserState(); } } From f26135e46d2869623c2a2cac6683ac99416507dc Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Tue, 29 Dec 2015 03:07:10 -0500 Subject: [PATCH 03/18] removed junk classes, added skeleton for RefreshCommand --- .../UI/CodeExplorer/CodeExplorerViewModel.cs | 51 ++++--------------- 1 file changed, 10 insertions(+), 41 deletions(-) diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs index b006feba0a..410e678bc9 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs @@ -3,9 +3,11 @@ using System.Collections.ObjectModel; using System.Text; using System.Threading.Tasks; +using System.Windows.Input; using Microsoft.Vbe.Interop; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; +using Rubberduck.UI.Command; namespace Rubberduck.UI.CodeExplorer { @@ -18,8 +20,13 @@ public CodeExplorerViewModel(RubberduckParserState state) _state = state; _state.StateChanged += ParserState_StateChanged; _state.ModuleStateChanged += ParserState_ModuleStateChanged; + + _refreshCommand = new DelegateCommand(ExecuteRefreshCommand); } + private readonly ICommand _refreshCommand; + public ICommand RefreshCommand { get { return _refreshCommand; } } + private bool _isBusy; public bool IsBusy { get { return _isBusy; } set { _isBusy = value; OnPropertyChanged(); } } @@ -30,50 +37,12 @@ private void ParserState_StateChanged(object sender, ParserStateEventArgs e) private void ParserState_ModuleStateChanged(object sender, Parsing.ParseProgressEventArgs e) { - - } - } - - public class ExplorerProjectItemViewModel : ViewModelBase - { - private readonly VBProject _project; - - public ExplorerProjectItemViewModel(VBProject project) - { - _project = project; - } - - public string Name { get { return _project.Name; } } - public bool IsProtected { get { return _project.Protection == vbext_ProjectProtection.vbext_pp_locked; } } - - - } - - public class ExplorerComponentItemViewModel : ViewModelBase - { - - } - - public class ExplorerMemberViewModel : ViewModelBase - { - private readonly Declaration _declaration; - private readonly ConcurrentStack _children = new ConcurrentStack(); - - public ExplorerMemberViewModel(Declaration declaration) - { - _declaration = declaration; - } - - public void AddChild(ExplorerMemberViewModel declaration) - { - _children.Push(declaration); + // todo: handle Error and Parsed states } - public void Clear() + private void ExecuteRefreshCommand(object param) { - _children.Clear(); + // todo: figure out how to expose member tree } - - public Declaration Declaration { get { return _declaration; } } } } From f6ac72bf98a0b9e35d85d985d8da0782d54f1434 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Wed, 30 Dec 2015 03:16:15 -0500 Subject: [PATCH 04/18] code explorer window builds and shows up... still without any content. --- RetailCoder.VBE/Rubberduck.csproj | 4 +- .../UI/CodeExplorer/CodeExplorerControl.xaml | 112 +-- .../CodeExplorer/CodeExplorerControl.xaml.cs | 5 - .../CodeExplorerDockablePresenter.cs | 714 +++++------------ .../UI/CodeExplorer/CodeExplorerViewModel.cs | 205 ++++- .../CodeExplorerWindow.Designer.cs | 273 +------ .../UI/CodeExplorer/CodeExplorerWindow.cs | 355 --------- .../UI/CodeExplorer/CodeExplorerWindow.resx | 741 +----------------- Rubberduck.Parsing/Grammar/Annotations.cs | 1 + 9 files changed, 409 insertions(+), 2001 deletions(-) diff --git a/RetailCoder.VBE/Rubberduck.csproj b/RetailCoder.VBE/Rubberduck.csproj index a06c42535c..53680efe6a 100644 --- a/RetailCoder.VBE/Rubberduck.csproj +++ b/RetailCoder.VBE/Rubberduck.csproj @@ -1096,8 +1096,8 @@ - - + + diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml index c100d8ddf5..bf46b89863 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml @@ -4,10 +4,11 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:explorer="clr-namespace:Rubberduck.UI.CodeExplorer" + xmlns:symbols="clr-namespace:Rubberduck.Parsing.Symbols;assembly=Rubberduck.Parsing" xmlns:resx="clr-namespace:Rubberduck.UI" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d" - d:DesignHeight="300" d:DesignWidth="300"> + d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance explorer:CodeExplorerViewModel}"> @@ -86,74 +87,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -175,19 +108,19 @@ - - - - - From 24400257610f4efb18aa4ab3655943bd4f6e7e6b Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Thu, 31 Dec 2015 01:19:24 -0500 Subject: [PATCH 06/18] made CodeExplorerCommand depend on IPresenter instead of concrete implementation; added SingletonScope Ninject binding for it, and wired up RefreshCommand. TreeView now displays content... but needs a HierarchicalDataTemplate. --- RetailCoder.VBE/Root/RubberduckModule.cs | 6 ++++++ .../UI/CodeExplorer/CodeExplorerControl.xaml | 20 +++++++++---------- .../CodeExplorer/CodeExplorerControl.xaml.cs | 4 +++- .../CodeExplorerDockablePresenter.cs | 5 +---- .../UI/CodeExplorer/CodeExplorerViewModel.cs | 11 +--------- .../UI/CodeExplorer/CodeExplorerWindow.cs | 16 ++++++++++----- .../UI/Command/CodeExplorerCommand.cs | 5 ++--- 7 files changed, 33 insertions(+), 34 deletions(-) diff --git a/RetailCoder.VBE/Root/RubberduckModule.cs b/RetailCoder.VBE/Root/RubberduckModule.cs index 419fe7038b..9c002d7950 100644 --- a/RetailCoder.VBE/Root/RubberduckModule.cs +++ b/RetailCoder.VBE/Root/RubberduckModule.cs @@ -15,6 +15,7 @@ using Rubberduck.Settings; using Rubberduck.SmartIndenter; using Rubberduck.UI; +using Rubberduck.UI.CodeExplorer; using Rubberduck.UI.CodeInspections; using Rubberduck.UI.Command; using Rubberduck.UI.UnitTesting; @@ -73,6 +74,11 @@ public override void Load() .InSingletonScope() .WithConstructorArgument(new CodeInspectionsWindow { ViewModel = _kernel.Get() }); + Bind().To() + .WhenInjectedInto() + .InSingletonScope() + .WithConstructorArgument(new CodeExplorerWindow { ViewModel = _kernel.Get() }); + BindWindowsHooks(); Debug.Print("completed RubberduckModule.Load()"); } diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml index 1406f1dde7..d1ce00b2e2 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml @@ -107,20 +107,17 @@ - + - + - + @@ -129,11 +126,12 @@ - + diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml.cs index 7e18d0886a..a67cf43373 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml.cs @@ -25,9 +25,11 @@ public CodeExplorerControl() InitializeComponent(); } + private CodeExplorerViewModel ViewModel { get { return DataContext as CodeExplorerViewModel; } } + private void TreeView_OnMouseDoubleClick(object sender, MouseButtonEventArgs e) { - throw new NotImplementedException(); + // todo: execute a NavigateCommand } } } diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerDockablePresenter.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerDockablePresenter.cs index d1e3d02940..ceab041e35 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerDockablePresenter.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerDockablePresenter.cs @@ -1,17 +1,14 @@ using Microsoft.Vbe.Interop; -using Rubberduck.Parsing.VBA; namespace Rubberduck.UI.CodeExplorer { public class CodeExplorerDockablePresenter : DockableToolwindowPresenter { - private readonly RubberduckParserState _state; private CodeExplorerWindow Control { get { return UserControl as CodeExplorerWindow; } } - public CodeExplorerDockablePresenter(RubberduckParserState state, VBE vbe, AddIn addIn, CodeExplorerWindow view) + public CodeExplorerDockablePresenter(VBE vbe, AddIn addIn, IDockableUserControl view) : base(vbe, addIn, view) { - _state = state; } //private string GetNodeText(Declaration declaration) diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs index 3cef181047..e06adcaa7d 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs @@ -24,15 +24,6 @@ public CodeExplorerViewModel(RubberduckParserState state) private readonly ICommand _refreshCommand; public ICommand RefreshCommand { get { return _refreshCommand; } } - private readonly ICommand _toggleSignaturesCommand; - public ICommand ToggleSignaturesCommand { get { return _toggleSignaturesCommand; } } - - private readonly ICommand _toggleNamespacesCommand; - public ICommand ToggleNamespacesCommand { get { return _toggleNamespacesCommand; } } - - private readonly ICommand _toggleFoldersCommand; - public ICommand ToggleFoldersCommand { get { return _toggleFoldersCommand; } } - private object _selectedItem; public object SelectedItem { @@ -82,7 +73,7 @@ public IEnumerable Projects private void ParserState_StateChanged(object sender, ParserStateEventArgs e) { IsBusy = e.State == ParserState.Parsing; - if (e.State != ParserState.Parsed) + if (e.State != ParserState.Resolving) // Parsed state is too volatile { return; } diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerWindow.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerWindow.cs index df59fc7f84..06e26af4c7 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerWindow.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerWindow.cs @@ -1,9 +1,5 @@ -using System; -using System.Diagnostics.CodeAnalysis; +using System.Diagnostics.CodeAnalysis; using System.Windows.Forms; -using Microsoft.Vbe.Interop; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Properties; namespace Rubberduck.UI.CodeExplorer { @@ -19,5 +15,15 @@ public CodeExplorerWindow() InitializeComponent(); } + private CodeExplorerViewModel _viewModel; + public CodeExplorerViewModel ViewModel + { + get { return _viewModel; } + set + { + _viewModel = value; + codeExplorerControl1.DataContext = _viewModel; + } + } } } diff --git a/RetailCoder.VBE/UI/Command/CodeExplorerCommand.cs b/RetailCoder.VBE/UI/Command/CodeExplorerCommand.cs index e5b00d6f86..fb0ccc290c 100644 --- a/RetailCoder.VBE/UI/Command/CodeExplorerCommand.cs +++ b/RetailCoder.VBE/UI/Command/CodeExplorerCommand.cs @@ -9,9 +9,9 @@ namespace Rubberduck.UI.Command [ComVisible(false)] public class CodeExplorerCommand : CommandBase { - private readonly CodeExplorerDockablePresenter _presenter; + private readonly IPresenter _presenter; - public CodeExplorerCommand(CodeExplorerDockablePresenter presenter) + public CodeExplorerCommand(IPresenter presenter) { _presenter = presenter; } @@ -20,6 +20,5 @@ public override void Execute(object parameter) { _presenter.Show(); } - } } \ No newline at end of file From b012989e2a19e65edb5ef87f9074df9260343f69 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Thu, 31 Dec 2015 01:52:07 -0500 Subject: [PATCH 07/18] Fixed reporting of error state and a bug in the collecting of module annotations --- RetailCoder.VBE/Rubberduck.csproj | 3 + .../CodeExplorerComponentViewModel.cs | 94 +++++++++++++ .../CodeExplorerMemberViewModel.cs | 18 +++ .../CodeExplorerProjectViewModel.cs | 33 +++++ .../UI/CodeExplorer/CodeExplorerViewModel.cs | 129 ------------------ .../Symbols/DeclarationSymbolsListener.cs | 3 +- Rubberduck.Parsing/VBA/RubberduckParser.cs | 22 ++- .../VBA/RubberduckParserState.cs | 5 +- 8 files changed, 170 insertions(+), 137 deletions(-) create mode 100644 RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs create mode 100644 RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs create mode 100644 RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs diff --git a/RetailCoder.VBE/Rubberduck.csproj b/RetailCoder.VBE/Rubberduck.csproj index 53680efe6a..04fbb8a116 100644 --- a/RetailCoder.VBE/Rubberduck.csproj +++ b/RetailCoder.VBE/Rubberduck.csproj @@ -391,9 +391,12 @@ BusyIndicator.xaml + CodeExplorerControl.xaml + + diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs new file mode 100644 index 0000000000..0803e04ea2 --- /dev/null +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs @@ -0,0 +1,94 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.Vbe.Interop; +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.UI.CodeExplorer +{ + public class CodeExplorerComponentViewModel : ViewModelBase + { + private readonly Declaration _declaration; + private readonly IEnumerable _members; + + private static readonly DeclarationType[] MemberTypes = + { + DeclarationType.Constant, + DeclarationType.Enumeration, + DeclarationType.Event, + DeclarationType.Function, + DeclarationType.LibraryFunction, + DeclarationType.LibraryProcedure, + DeclarationType.Procedure, + DeclarationType.PropertyGet, + DeclarationType.PropertyLet, + DeclarationType.PropertySet, + DeclarationType.UserDefinedType, + DeclarationType.Variable, + }; + + public CodeExplorerComponentViewModel(Declaration declaration, IEnumerable declarations) + { + _declaration = declaration; + _members = declarations.GroupBy(item => item.Scope) + .SelectMany(grouping => + grouping.Where(item => MemberTypes.Contains(item.DeclarationType)) + .Select(item => new CodeExplorerMemberViewModel(item))); + + var ns = _declaration.Annotations + .Split('\n') + .FirstOrDefault(annotation => annotation.StartsWith(Parsing.Grammar.Annotations.Namespace)); + + if (ns != null) + { + + var value = ns.Split(' '); + _namespace = value.Length == 1 ? string.Empty : value[1]; + } + else + { + _namespace = string.Empty; + } + } + + private bool _isErrorState; + public bool IsErrorState { get { return _isErrorState; } set { _isErrorState = value; OnPropertyChanged(); } } + + public bool IsTestModule + { + get + { + return _declaration.DeclarationType == DeclarationType.Module + && _declaration.Annotations.Split('\n').Contains(Parsing.Grammar.Annotations.TestModule); + } + } + + public string Name { get { return _declaration.IdentifierName; } } + + private readonly string _namespace; + public string Namespace { get { return _namespace; } } + + private vbext_ComponentType ComponentType { get { return _declaration.QualifiedName.QualifiedModuleName.Component.Type; } } + + private static readonly IDictionary DeclarationTypes = new Dictionary + { + { vbext_ComponentType.vbext_ct_ClassModule, DeclarationType.Class }, + { vbext_ComponentType.vbext_ct_StdModule, DeclarationType.Module }, + { vbext_ComponentType.vbext_ct_Document, DeclarationType.Document }, + { vbext_ComponentType.vbext_ct_MSForm, DeclarationType.UserForm } + }; + + public DeclarationType DeclarationType + { + get + { + DeclarationType result; + if (!DeclarationTypes.TryGetValue(ComponentType, out result)) + { + result = DeclarationType.Class; + } + + return result; + } + } + } +} \ No newline at end of file diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs new file mode 100644 index 0000000000..de03924319 --- /dev/null +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs @@ -0,0 +1,18 @@ +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.UI.CodeExplorer +{ + public class CodeExplorerMemberViewModel : ViewModelBase + { + private readonly Declaration _declaration; + + public CodeExplorerMemberViewModel(Declaration declaration) + { + _declaration = declaration; + } + + public string Name { get { return _declaration.IdentifierName; } } + //public string Signature { get { return _declaration.IdentifierName; } } + + } +} \ No newline at end of file diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs new file mode 100644 index 0000000000..9bbc1a90cc --- /dev/null +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using System.Linq; +using Microsoft.Vbe.Interop; +using Rubberduck.Parsing.Symbols; + +namespace Rubberduck.UI.CodeExplorer +{ + public class CodeExplorerProjectViewModel : ViewModelBase + { + private readonly Declaration _declaration; + private readonly IEnumerable _components; + + private static readonly DeclarationType[] ComponentTypes = + { + DeclarationType.Class, + DeclarationType.Document, + DeclarationType.Module, + DeclarationType.UserForm, + }; + + public CodeExplorerProjectViewModel(Declaration declaration, IEnumerable declarations) + { + _declaration = declaration; + _components = declarations.GroupBy(item => item.ComponentName) + .SelectMany(grouping => + grouping.Where(item => ComponentTypes.Contains(item.DeclarationType)) + .Select(item => new CodeExplorerComponentViewModel(item, grouping))); + } + + public bool IsProtected { get { return _declaration.Project.Protection == vbext_ProjectProtection.vbext_pp_locked; } } + public IEnumerable Components { get { return _components; } } + } +} \ No newline at end of file diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs index e06adcaa7d..a03ac7e3e6 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs @@ -1,7 +1,6 @@ using System.Collections.Generic; using System.Linq; using System.Windows.Input; -using Microsoft.Vbe.Interop; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.UI.Command; @@ -97,132 +96,4 @@ private void ExecuteRefreshCommand(object param) _state.OnParseRequested(); } } - - public class CodeExplorerProjectViewModel : ViewModelBase - { - private readonly Declaration _declaration; - private readonly IEnumerable _components; - - private static readonly DeclarationType[] ComponentTypes = - { - DeclarationType.Class, - DeclarationType.Document, - DeclarationType.Module, - DeclarationType.UserForm, - }; - - public CodeExplorerProjectViewModel(Declaration declaration, IEnumerable declarations) - { - _declaration = declaration; - _components = declarations.GroupBy(item => item.ComponentName) - .SelectMany(grouping => - grouping.Where(item => ComponentTypes.Contains(item.DeclarationType)) - .Select(item => new CodeExplorerComponentViewModel(item, grouping))); - } - - public bool IsProtected { get { return _declaration.Project.Protection == vbext_ProjectProtection.vbext_pp_locked; } } - public IEnumerable Components { get { return _components; } } - } - - public class CodeExplorerComponentViewModel : ViewModelBase - { - private readonly Declaration _declaration; - private readonly IEnumerable _members; - - private static readonly DeclarationType[] MemberTypes = - { - DeclarationType.Constant, - DeclarationType.Enumeration, - DeclarationType.Event, - DeclarationType.Function, - DeclarationType.LibraryFunction, - DeclarationType.LibraryProcedure, - DeclarationType.Procedure, - DeclarationType.PropertyGet, - DeclarationType.PropertyLet, - DeclarationType.PropertySet, - DeclarationType.UserDefinedType, - DeclarationType.Variable, - }; - - public CodeExplorerComponentViewModel(Declaration declaration, IEnumerable declarations) - { - _declaration = declaration; - _members = declarations.GroupBy(item => item.Scope) - .SelectMany(grouping => - grouping.Where(item => MemberTypes.Contains(item.DeclarationType)) - .Select(item => new CodeExplorerMemberViewModel(item))); - } - - private bool _isErrorState; - public bool IsErrorState { get { return _isErrorState; } set { _isErrorState = value; OnPropertyChanged(); } } - - public bool IsTestModule - { - get - { - return _declaration.DeclarationType == DeclarationType.Module - && _declaration.Annotations.Split('\n').Contains(Parsing.Grammar.Annotations.TestModule); - } - } - - public string Name { get { return _declaration.IdentifierName; } } - - public string Namespace - { - get - { - var result = _declaration.Annotations - .Split('\n') - .FirstOrDefault(annotation => annotation.StartsWith(Parsing.Grammar.Annotations.Namespace)); - - if (result == null) - { - return string.Empty; - } - - // don't throw in getter, but if value.Length > 2 then anything after the 2nd space is ignored: - var value = result.Split(' '); - return value.Length == 1 ? string.Empty : value[1]; - } - } - - private vbext_ComponentType ComponentType { get { return _declaration.QualifiedName.QualifiedModuleName.Component.Type; } } - - private static readonly IDictionary DeclarationTypes = new Dictionary - { - { vbext_ComponentType.vbext_ct_ClassModule, DeclarationType.Class }, - { vbext_ComponentType.vbext_ct_StdModule, DeclarationType.Module }, - { vbext_ComponentType.vbext_ct_Document, DeclarationType.Document }, - { vbext_ComponentType.vbext_ct_MSForm, DeclarationType.UserForm } - }; - - public DeclarationType DeclarationType - { - get - { - DeclarationType result; - if (!DeclarationTypes.TryGetValue(ComponentType, out result)) - { - result = DeclarationType.Class; - } - - return result; - } - } - } - - public class CodeExplorerMemberViewModel : ViewModelBase - { - private readonly Declaration _declaration; - - public CodeExplorerMemberViewModel(Declaration declaration) - { - _declaration = declaration; - } - - public string Name { get { return _declaration.IdentifierName; } } - //public string Signature { get { return _declaration.IdentifierName; } } - - } } diff --git a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs index 2cc60c47f5..3d8cf4952f 100644 --- a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs +++ b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs @@ -30,7 +30,8 @@ private string FindAnnotations() } var lastDeclarationsSectionLine = _qualifiedName.Component.CodeModule.CountOfDeclarationLines; - var annotations = _comments.Where(comment => comment.QualifiedSelection.Selection.EndLine <= lastDeclarationsSectionLine + var annotations = _comments.Where(comment => comment.QualifiedSelection.QualifiedName.Equals(_qualifiedName) + && comment.QualifiedSelection.Selection.EndLine <= lastDeclarationsSectionLine && comment.CommentText.StartsWith("@")).ToArray(); if (annotations.Any()) diff --git a/Rubberduck.Parsing/VBA/RubberduckParser.cs b/Rubberduck.Parsing/VBA/RubberduckParser.cs index 1798ad3918..c876a187bf 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParser.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParser.cs @@ -106,6 +106,10 @@ public Task ParseAsync(VBComponent vbComponent, CancellationToken token) { var parseTask = Task.Run(() => ParseInternal(component, token), token); parseTask.Wait(token); + if (parseTask.IsFaulted) + { + Debug.Print(parseTask.Exception.ToString()); + } } catch (COMException exception) { @@ -197,13 +201,23 @@ private void ParseInternal(VBComponent vbComponent, CancellationToken token) token.ThrowIfCancellationRequested(); - ITokenStream stream; var code = string.Join(Environment.NewLine, vbComponent.CodeModule.Code()); - var tree = ParseInternal(code, listeners, out stream); + IParseTree tree; + + try + { + ITokenStream stream; + tree = ParseInternal(code, listeners, out stream); + _state.AddTokenStream(vbComponent, stream); + _state.AddParseTree(vbComponent, tree); + } + catch (SyntaxErrorException) + { + State.SetModuleState(vbComponent, ParserState.Error); + throw; + } token.ThrowIfCancellationRequested(); - _state.AddTokenStream(vbComponent, stream); - _state.AddParseTree(vbComponent, tree); // cannot locate declarations in one pass *the way it's currently implemented*, // because the context in EnterSubStmt() doesn't *yet* have child nodes when the context enters. diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs index 25e08451da..771198e7ea 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs @@ -74,12 +74,11 @@ private void OnModuleStateChanged(VBComponent component, ParserState state) public void SetModuleState(VBComponent component, ParserState state, SyntaxErrorException parserError = null) { - _moduleStates[component] = state; - _moduleExceptions[component] = parserError; - // prevent multiple threads from changing state simultaneously: lock(_lock) { + _moduleStates[component] = state; + _moduleExceptions[component] = parserError; OnModuleStateChanged(component, state); Status = EvaluateParserState(); } From ad504141f6fa556bfa1967853da08927c5df5d0a Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Tue, 5 Jan 2016 00:45:04 -0500 Subject: [PATCH 08/18] parser is now async only when a reparse is requested - that should help with testing. failing resolver hangs in "resolving" state though. --- RetailCoder.VBE/App.cs | 2 +- .../ObsoleteCommentSyntaxInspection.cs | 2 +- .../ToDoExplorerDockablePresenter.cs | 2 +- Rubberduck.Parsing/IRubberduckParser.cs | 7 +- .../Symbols/DeclarationSymbolsListener.cs | 78 ++++++------ .../Symbols/ExcelObjectModel.cs | 36 ++++-- .../Symbols/IdentifierReferenceResolver.cs | 42 ++++--- Rubberduck.Parsing/VBA/RubberduckParser.cs | 115 +++++++++++------- .../VBA/RubberduckParserState.cs | 13 +- .../Extensions/CodeModuleExtensions.cs | 5 +- 10 files changed, 190 insertions(+), 112 deletions(-) diff --git a/RetailCoder.VBE/App.cs b/RetailCoder.VBE/App.cs index 765f49e4bb..d7f8099cf4 100644 --- a/RetailCoder.VBE/App.cs +++ b/RetailCoder.VBE/App.cs @@ -92,7 +92,7 @@ private async void hooks_MessageReceived(object sender, HookEventArgs e) } var component = _vbe.ActiveCodePane.CodeModule.Parent; - _parser.ParseComponentAsync(component); + _parser.ParseComponent(component); AwaitNextKey(); return; diff --git a/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs index 2b701f4181..802d77d795 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs @@ -24,7 +24,7 @@ public ObsoleteCommentSyntaxInspection() public IEnumerable GetInspectionResults(RubberduckParserState state) { - return (state.Comments.Where(comment => comment.Marker == Tokens.Rem) + return (state.AllComments.Where(comment => comment.Marker == Tokens.Rem) .Select(comment => new ObsoleteCommentSyntaxInspectionResult(this, comment))); } } diff --git a/RetailCoder.VBE/UI/ToDoItems/ToDoExplorerDockablePresenter.cs b/RetailCoder.VBE/UI/ToDoItems/ToDoExplorerDockablePresenter.cs index 6e944d31ee..94a9347f46 100644 --- a/RetailCoder.VBE/UI/ToDoItems/ToDoExplorerDockablePresenter.cs +++ b/RetailCoder.VBE/UI/ToDoItems/ToDoExplorerDockablePresenter.cs @@ -85,7 +85,7 @@ private void SortColumn(object sender, DataGridViewCellMouseEventArgs e) private async Task> GetItems() { - var markers = _parser.State.Comments.SelectMany(GetToDoMarkers).ToList(); + var markers = _parser.State.AllComments.SelectMany(GetToDoMarkers).ToList(); var sortedItems = markers.OrderByDescending(item => item.Priority) .ThenBy(item => item.ProjectName) .ThenBy(item => item.ModuleName) diff --git a/Rubberduck.Parsing/IRubberduckParser.cs b/Rubberduck.Parsing/IRubberduckParser.cs index 749c29bf0a..a5a6df06bd 100644 --- a/Rubberduck.Parsing/IRubberduckParser.cs +++ b/Rubberduck.Parsing/IRubberduckParser.cs @@ -1,5 +1,6 @@ using System.Threading; using System.Threading.Tasks; +using Antlr4.Runtime; using Microsoft.Vbe.Interop; using Rubberduck.Parsing.VBA; @@ -8,8 +9,8 @@ namespace Rubberduck.Parsing public interface IRubberduckParser { RubberduckParserState State { get; } - void ParseComponentAsync(VBComponent component, bool resolve = true); - Task ParseAsync(VBComponent component, CancellationToken token); - void Resolve(CancellationToken token); + void ParseComponent(VBComponent component, bool resolve = true, TokenStreamRewriter rewriter = null); + //Task ParseAsync(VBComponent component, CancellationToken token, TokenStreamRewriter rewriter = null); + //void Resolve(CancellationToken token); } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs index 3d8cf4952f..4e579494cb 100644 --- a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs +++ b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs @@ -22,42 +22,6 @@ public class DeclarationSymbolsListener : VBABaseListener private readonly IEnumerable _comments; private readonly CancellationToken _token; - private string FindAnnotations() - { - if (_comments == null) - { - return null; - } - - var lastDeclarationsSectionLine = _qualifiedName.Component.CodeModule.CountOfDeclarationLines; - var annotations = _comments.Where(comment => comment.QualifiedSelection.QualifiedName.Equals(_qualifiedName) - && comment.QualifiedSelection.Selection.EndLine <= lastDeclarationsSectionLine - && comment.CommentText.StartsWith("@")).ToArray(); - - if (annotations.Any()) - { - return string.Join("\n", annotations.Select(annotation => annotation.CommentText)); - } - - return null; - } - - private string FindAnnotations(int line) - { - if (_comments == null) - { - return null; - } - - var commentAbove = _comments.SingleOrDefault(comment => comment.QualifiedSelection.Selection.EndLine == line - 1); - if (commentAbove != null && commentAbove.CommentText.StartsWith("@")) - { - return commentAbove.CommentText; - } - - return null; - } - public DeclarationSymbolsListener(QualifiedModuleName qualifiedName, Accessibility componentAccessibility, vbext_ComponentType type, IEnumerable comments, CancellationToken token) { _qualifiedName = qualifiedName; @@ -96,6 +60,48 @@ public DeclarationSymbolsListener(QualifiedModuleName qualifiedName, Accessibili SetCurrentScope(); } + private string FindAnnotations() + { + if (_comments == null) + { + return null; + } + + var lastDeclarationsSectionLine = _qualifiedName.Component.CodeModule.CountOfDeclarationLines; + var annotations = _comments.Where(comment => comment.QualifiedSelection.QualifiedName.Equals(_qualifiedName) + && comment.QualifiedSelection.Selection.EndLine <= lastDeclarationsSectionLine + && comment.CommentText.StartsWith("@")).ToArray(); + + if (annotations.Any()) + { + return string.Join("\n", annotations.Select(annotation => annotation.CommentText)); + } + + return null; + } + + private string FindAnnotations(int line) + { + if (_comments == null) + { + return null; + } + + try + { + var commentAbove = _comments.SingleOrDefault(comment => comment.QualifiedSelection.Selection.EndLine == line - 1); + if (commentAbove != null && commentAbove.CommentText.StartsWith("@")) + { + return commentAbove.CommentText; + } + } + catch (InvalidOperationException) + { + throw; + } + return null; + } + public void CreateModuleDeclarations() { OnNewDeclaration(_projectDeclaration); diff --git a/Rubberduck.Parsing/Symbols/ExcelObjectModel.cs b/Rubberduck.Parsing/Symbols/ExcelObjectModel.cs index 36e7192d1e..eb6741fd97 100644 --- a/Rubberduck.Parsing/Symbols/ExcelObjectModel.cs +++ b/Rubberduck.Parsing/Symbols/ExcelObjectModel.cs @@ -32,15 +32,7 @@ public static IEnumerable Declarations private class ExcelLib { public static readonly Declaration Excel = new Declaration(new QualifiedMemberName(ExcelModuleName, "Excel"), null, "Excel", "Excel", true, false, Accessibility.Global, DeclarationType.Project); - - private static readonly QualifiedModuleName RangeModuleName = new QualifiedModuleName("Excel", "Range"); - public static readonly Declaration Range = new Declaration(new QualifiedMemberName(RangeModuleName, "Range"), ExcelLib.Excel, "Excel", "Range", false, false, Accessibility.Global, DeclarationType.Class); - - public static Declaration Activate = new Declaration(new QualifiedMemberName(RangeModuleName, "Activate"), Range, "Excel.Range", "Variant", false, false, Accessibility.Global, DeclarationType.Function); - public static Declaration Address = new Declaration(new QualifiedMemberName(RangeModuleName, "Address"), Range, "Excel.Range", "String", false, false, Accessibility.Global, DeclarationType.PropertyGet); - public static Declaration Select = new Declaration(new QualifiedMemberName(RangeModuleName, "Select"), Range, "Excel.Range", "Variant", false, false, Accessibility.Global, DeclarationType.Function); - public static Declaration Cells = new Declaration(new QualifiedMemberName(RangeModuleName, "Cells"), Range, "Excel.Range", "Range", false, false, Accessibility.Global, DeclarationType.PropertyGet); - public static Declaration Formula = new Declaration(new QualifiedMemberName(RangeModuleName, "Formula"), Range, "Excel.Range", "Variant", false, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration Application = new Declaration(new QualifiedMemberName(ExcelModuleName, "Application"), Excel, "Excel.Application", "Application", false, false, Accessibility.Global, DeclarationType.PropertyGet); } @@ -111,5 +103,31 @@ private class GlobalClass public static Declaration ActiveSheet = new Declaration(new QualifiedMemberName(ExcelModuleName, "ActiveSheet"), Global, "Excel.Global", "Worksheet", false, false, Accessibility.Global, DeclarationType.PropertyGet); // cheating on return type public static Declaration ActiveWorkbook = new Declaration(new QualifiedMemberName(ExcelModuleName, "ActiveWorkbook"), Global, "Excel.Global", "Workbook", false, false, Accessibility.Global, DeclarationType.PropertyGet); } + + private class ApplicationClass + { + public static readonly Declaration Application = new Declaration(new QualifiedMemberName(ExcelModuleName, "Application"), ExcelLib.Excel, "Application", "Application", false, false, Accessibility.Global, DeclarationType.Module); // cheating, it's actually a class. + + public static Declaration Evaluate = new Declaration(new QualifiedMemberName(ExcelModuleName, "Evaluate"), Application, "Excel.Application", "Variant", false, false, Accessibility.Global, DeclarationType.Function); + public static Declaration Range = new Declaration(new QualifiedMemberName(ExcelModuleName, "Range"), Application, "Excel.Application", "Range", true, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration RangeAssign = new Declaration(new QualifiedMemberName(ExcelModuleName, "Range"), Application, "Excel.Application", "Range", true, false, Accessibility.Global, DeclarationType.PropertyLet); // cheating to simuate default property of return type. + public static Declaration Selection = new Declaration(new QualifiedMemberName(ExcelModuleName, "Selection"), Application, "Excel.Application", "Object", true, false, Accessibility.Global, DeclarationType.PropertyGet); + + public static Declaration Activate = new Declaration(new QualifiedMemberName(ExcelModuleName, "Activate"), Application, "Excel.Application", "Variant", false, false, Accessibility.Global, DeclarationType.Function); + public static Declaration Select = new Declaration(new QualifiedMemberName(ExcelModuleName, "Select"), Application, "Excel.Application", "Variant", false, false, Accessibility.Global, DeclarationType.Function); + public static Declaration Cells = new Declaration(new QualifiedMemberName(ExcelModuleName, "Cells"), Application, "Excel.Application", "Range", false, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration CellsAssign = new Declaration(new QualifiedMemberName(ExcelModuleName, "Cells"), Application, "Excel.Application", "Range", false, false, Accessibility.Global, DeclarationType.PropertyLet); // cheating to simulate default property of return type. + public static Declaration Names = new Declaration(new QualifiedMemberName(ExcelModuleName, "Names"), Application, "Excel.Application", "Names", false, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration Sheets = new Declaration(new QualifiedMemberName(ExcelModuleName, "Sheets"), Application, "Excel.Application", "Sheets", false, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration Worksheets = new Declaration(new QualifiedMemberName(ExcelModuleName, "Worksheets"), Application, "Excel.Application", "Worksheets", false, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration WorksheetFunction = new Declaration(new QualifiedMemberName(ExcelModuleName, "WorksheetFunction"), Application, "Excel.Application", "WorksheetFunction", false, false, Accessibility.Global, DeclarationType.PropertyGet); + + public static Declaration Columns = new Declaration(new QualifiedMemberName(ExcelModuleName, "Columns"), Application, "Excel.Application", "Range", false, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration Rows = new Declaration(new QualifiedMemberName(ExcelModuleName, "Rows"), Application, "Excel.Application", "Range", false, false, Accessibility.Global, DeclarationType.PropertyGet); + + public static Declaration ActiveCell = new Declaration(new QualifiedMemberName(ExcelModuleName, "ActiveCell"), Application, "Excel.Application", "Range", false, false, Accessibility.Global, DeclarationType.PropertyGet); + public static Declaration ActiveSheet = new Declaration(new QualifiedMemberName(ExcelModuleName, "ActiveSheet"), Application, "Excel.Application", "Worksheet", false, false, Accessibility.Global, DeclarationType.PropertyGet); // cheating on return type + public static Declaration ActiveWorkbook = new Declaration(new QualifiedMemberName(ExcelModuleName, "ActiveWorkbook"), Application, "Excel.Application", "Workbook", false, false, Accessibility.Global, DeclarationType.PropertyGet); + } } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs b/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs index a8e9d86f71..7c7879c935 100644 --- a/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs +++ b/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs @@ -202,25 +202,34 @@ private Declaration ResolveType(Declaration parent) ? parent.AsTypeName.Split('.').Last() : parent.AsTypeName; - var result = _declarations.Where(d => d.IdentifierName == identifier).SingleOrDefault(item => - item.DeclarationType == DeclarationType.UserDefinedType - && item.Project == _currentScope.Project - && item.ComponentName == _currentScope.ComponentName); + var matches = _declarations.Where(d => d.IdentifierName == identifier).ToList(); - if (result == null) + try { - result = _declarations.Where(d => d.IdentifierName == identifier).SingleOrDefault(item => - _moduleTypes.Contains(item.DeclarationType) - && item.Project == _currentScope.Project); - } + var result = matches.SingleOrDefault(item => + item.DeclarationType == DeclarationType.UserDefinedType + && item.Project == _currentScope.Project + && item.ComponentName == _currentScope.ComponentName); - if (result == null) + if (result == null) + { + result = matches.SingleOrDefault(item => + _moduleTypes.Contains(item.DeclarationType) + && item.Project == _currentScope.Project); + } + + if (result == null) + { + result = matches.SingleOrDefault(item => + _moduleTypes.Contains(item.DeclarationType)); + } + + return result; + } + catch (InvalidOperationException) { - result = _declarations.Where(d => d.IdentifierName == identifier).SingleOrDefault(item => - _moduleTypes.Contains(item.DeclarationType)); + return null; } - - return result; } private static readonly Type[] IdentifierContexts = @@ -369,6 +378,11 @@ private Declaration ResolveInternal(VBAParser.ICS_S_ProcedureOrArrayCallContext var fieldCall = context.dictionaryCallStmt(); // todo: understand WTF [baseType] is doing in that grammar rule... + if (localScope == null) + { + localScope = _currentScope; + } + var result = ResolveInternal(identifierContext, localScope, accessorType, fieldCall, hasExplicitLetStatement, isAssignmentTarget); if (result != null && !localScope.DeclarationType.HasFlag(DeclarationType.Member)) { diff --git a/Rubberduck.Parsing/VBA/RubberduckParser.cs b/Rubberduck.Parsing/VBA/RubberduckParser.cs index c876a187bf..414b75d764 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParser.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParser.cs @@ -31,7 +31,7 @@ public RubberduckParser(VBE vbe, RubberduckParserState state) private void ReparseRequested(object sender, EventArgs e) { - ParseAll(); + Task.Run(() => ParseParallel()); } private readonly VBE _vbe; @@ -41,12 +41,12 @@ private void ReparseRequested(object sender, EventArgs e) private readonly ConcurrentDictionary _tokenSources = new ConcurrentDictionary(); - public void ParseComponentAsync(VBComponent component, bool resolve = true) + public void ParseComponent(VBComponent component, bool resolve = true, TokenStreamRewriter rewriter = null) { var tokenSource = RenewTokenSource(component); var token = tokenSource.Token; - ParseAsync(component, token); + Parse(component, token, rewriter); if (resolve && !token.IsCancellationRequested) { @@ -75,41 +75,48 @@ private CancellationTokenSource RenewTokenSource(VBComponent component) return tokenSource; } - private void ParseAll() + private void ParseParallel() { - var components = _vbe.VBProjects.Cast() - .SelectMany(project => project.VBComponents.Cast()) - .ToList(); - - foreach (var vbComponent in components) + try { - _state.SetModuleState(vbComponent, ParserState.Pending); - } + var components = _vbe.VBProjects.Cast() + .SelectMany(project => project.VBComponents.Cast()) + .ToList(); - var result = Parallel.ForEach(components, component => { ParseComponentAsync(component, false); }); + foreach (var vbComponent in components) + { + _state.SetModuleState(vbComponent, ParserState.Pending); + } - if (result.IsCompleted) - { - using (var tokenSource = new CancellationTokenSource()) + var result = Parallel.ForEach(components, component => { ParseComponent(component, false); }); + + if (result.IsCompleted) { - Resolve(tokenSource.Token); + using (var tokenSource = new CancellationTokenSource()) + { + Resolve(tokenSource.Token); + } } } + catch (Exception exception) + { + Debug.Print(exception.ToString()); + } } - public Task ParseAsync(VBComponent vbComponent, CancellationToken token) + private void Parse(VBComponent vbComponent, CancellationToken token, TokenStreamRewriter rewriter = null) { var component = vbComponent; - token.ThrowIfCancellationRequested(); try { - var parseTask = Task.Run(() => ParseInternal(component, token), token); - parseTask.Wait(token); - if (parseTask.IsFaulted) - { - Debug.Print(parseTask.Exception.ToString()); - } + token.ThrowIfCancellationRequested(); + + var code = rewriter == null + ? string.Join(Environment.NewLine, vbComponent.CodeModule.GetSanitizedCode()) + : rewriter.GetText(); // note: removes everything ignored by the parser, e.g. line numbers and comments + + ParseInternal(component, code, token); } catch (COMException exception) { @@ -123,25 +130,39 @@ public Task ParseAsync(VBComponent vbComponent, CancellationToken token) } catch (OperationCanceledException) { - // no need to blow up + State.SetModuleState(component, ParserState.Error); + } + catch (Exception exception) + { + // break here, inspect and debug. + throw; } - return null; + return; } public void Resolve(CancellationToken token) { - var options = new ParallelOptions { CancellationToken = token }; - Parallel.ForEach(_state.ParseTrees, options, kvp => + try { - token.ThrowIfCancellationRequested(); - ResolveReferences(kvp.Key, kvp.Value, token); - }); + var options = new ParallelOptions { CancellationToken = token }; + Parallel.ForEach(_state.ParseTrees, options, kvp => + { + token.ThrowIfCancellationRequested(); + ResolveReferences(kvp.Key, kvp.Value, token); + }); + } + catch (OperationCanceledException) + { + // let it go... + } } private IEnumerable ParseComments(QualifiedModuleName qualifiedName) { - var code = qualifiedName.Component.CodeModule.Code(); + var result = new List(); + + var code = qualifiedName.Component.CodeModule.GetSanitizedCode(); var commentBuilder = new StringBuilder(); var continuing = false; @@ -166,10 +187,9 @@ private IEnumerable ParseComments(QualifiedModuleName qualifiedName commentBuilder.Append(line.Substring(index, commentLength).TrimStart()); var selection = new Selection(startLine + 1, startColumn + 1, i + 1, line.Length + 1); - var result = new CommentNode(commentBuilder.ToString(), new QualifiedSelection(qualifiedName, selection)); + var comment = new CommentNode(commentBuilder.ToString(), new QualifiedSelection(qualifiedName, selection)); commentBuilder.Clear(); - - yield return result; + result.Add(comment); } else { @@ -178,15 +198,18 @@ private IEnumerable ParseComments(QualifiedModuleName qualifiedName } } } + + return result; } - private void ParseInternal(VBComponent vbComponent, CancellationToken token) + private void ParseInternal(VBComponent vbComponent, string code, CancellationToken token) { _state.ClearDeclarations(vbComponent); State.SetModuleState(vbComponent, ParserState.Parsing); var qualifiedName = new QualifiedModuleName(vbComponent); - _state.SetModuleComments(vbComponent, ParseComments(qualifiedName)); + var comments = ParseComments(qualifiedName); + _state.SetModuleComments(vbComponent, comments); var obsoleteCallsListener = new ObsoleteCallStatementListener(); var obsoleteLetListener = new ObsoleteLetStatementListener(); @@ -201,7 +224,6 @@ private void ParseInternal(VBComponent vbComponent, CancellationToken token) token.ThrowIfCancellationRequested(); - var code = string.Join(Environment.NewLine, vbComponent.CodeModule.Code()); IParseTree tree; try @@ -211,9 +233,9 @@ private void ParseInternal(VBComponent vbComponent, CancellationToken token) _state.AddTokenStream(vbComponent, stream); _state.AddParseTree(vbComponent, tree); } - catch (SyntaxErrorException) + catch (SyntaxErrorException exception) { - State.SetModuleState(vbComponent, ParserState.Error); + State.SetModuleState(vbComponent, ParserState.Error, exception); throw; } @@ -222,7 +244,7 @@ private void ParseInternal(VBComponent vbComponent, CancellationToken token) // cannot locate declarations in one pass *the way it's currently implemented*, // because the context in EnterSubStmt() doesn't *yet* have child nodes when the context enters. // so we need to EnterAmbiguousIdentifier() and evaluate the parent instead - this *might* work. - var declarationsListener = new DeclarationSymbolsListener(qualifiedName, Accessibility.Implicit, vbComponent.Type, _state.Comments, token); + var declarationsListener = new DeclarationSymbolsListener(qualifiedName, Accessibility.Implicit, vbComponent.Type, _state.GetModuleComments(vbComponent), token); token.ThrowIfCancellationRequested(); declarationsListener.NewDeclaration += declarationsListener_NewDeclaration; @@ -242,8 +264,13 @@ private void ParseInternal(VBComponent vbComponent, CancellationToken token) private IParseTree ParseInternal(string code, IEnumerable listeners, out ITokenStream outStream) { - var input = new AntlrInputStream(code); - var lexer = new VBALexer(input); + var stream = new AntlrInputStream(code); + return ParseInternal(stream, listeners, out outStream); + } + + private IParseTree ParseInternal(ICharStream stream, IEnumerable listeners, out ITokenStream outStream) + { + var lexer = new VBALexer(stream); var tokens = new CommonTokenStream(lexer); var parser = new VBAParser(tokens); @@ -278,7 +305,7 @@ private void ResolveReferences(VBComponent component, IParseTree tree, Cancellat { walker.Walk(listener, tree); } - catch(WalkerCancelledException) + catch (WalkerCancelledException) { // move on } diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs index 771198e7ea..f4707991a9 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs @@ -169,7 +169,7 @@ public IEnumerable EmptyStringLiterals private readonly ConcurrentDictionary> _comments = new ConcurrentDictionary>(); - public IEnumerable Comments + public IEnumerable AllComments { get { @@ -177,6 +177,17 @@ public IEnumerable Comments } } + public IEnumerable GetModuleComments(VBComponent component) + { + IEnumerable result; + if (_comments.TryGetValue(component, out result)) + { + return result; + } + + return new List(); + } + public void SetModuleComments(VBComponent component, IEnumerable comments) { _comments[component] = comments; diff --git a/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs b/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs index 5fbd04f870..636e3e4604 100644 --- a/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs +++ b/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs @@ -8,9 +8,10 @@ namespace Rubberduck.VBEditor.Extensions public static class CodeModuleExtensions { /// - /// Gets an array of strings where each element is a line of code in the Module. + /// Gets an array of strings where each element is a line of code in the Module, + /// with line numbers stripped and any other pre-processing that needs to be done. /// - public static string[] Code(this CodeModule module) + public static string[] GetSanitizedCode(this CodeModule module) { var lines = module.CountOfLines; if (lines == 0) From 190409e077af4740406fc8a0af0b55a19e926bcf Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 00:14:35 -0500 Subject: [PATCH 09/18] fixed command.CanExecute; sealed inspection classes, introduced InspectionBase abstract class, account for @Ignore annotations, and enabled UnassignedVariableUsageInspection. --- .../AssignedByValParameterInspection.cs | 23 +++++-------- .../Inspections/ConstantNotUsedInspection.cs | 16 ++++----- .../DefaultProjectNameInspection.cs | 18 +++++----- .../EmptyStringLiteralInspection.cs | 22 +++++------- RetailCoder.VBE/Inspections/IInspection.cs | 34 ++++++++++++++++++- .../ImplicitActiveSheetReferenceInspection.cs | 16 ++++----- ...plicitActiveWorkbookReferenceInspection.cs | 22 ++++++------ .../ImplicitByRefParameterInspection.cs | 23 +++++-------- .../ImplicitPublicMemberInspection.cs | 18 ++++------ .../ImplicitVariantReturnTypeInspection.cs | 18 ++++------ .../Inspections/InspectionsUI.Designer.cs | 31 +++++++++++++++-- .../Inspections/InspectionsUI.resx | 11 +++++- RetailCoder.VBE/Inspections/Inspector.cs | 2 +- .../MultilineParameterInspection.cs | 16 ++++----- .../MultipleDeclarationsInspection.cs | 18 ++++------ .../NonReturningFunctionInspection.cs | 16 ++++----- .../ObsoleteCallStatementInspection.cs | 16 ++++----- .../ObsoleteCommentSyntaxInspection.cs | 18 +++++----- .../Inspections/ObsoleteGlobalInspection.cs | 16 ++++----- .../ObsoleteLetStatementInspection.cs | 16 ++++----- .../Inspections/ObsoleteTypeHintInspection.cs | 16 ++++----- .../Inspections/OptionBaseInspection.cs | 21 +++++------- .../Inspections/OptionExplicitInspection.cs | 16 ++++----- .../ParameterCanBeByValInspection.cs | 16 ++++----- .../Inspections/ParameterNotUsedInspection.cs | 20 +++++------ .../Inspections/ProcedureNotUsedInspection.cs | 16 ++++----- .../UnassignedVariableUsageInspection.cs | 22 +++++------- .../UntypedFunctionUsageInspection.cs | 16 ++++----- .../UseMeaningfulNameInspection.cs | 18 +++++----- .../VariableNotAssignedInspection.cs | 16 ++++----- .../Inspections/VariableNotUsedInspection.cs | 16 ++++----- .../VariableTypeNotDeclaredInspection.cs | 16 ++++----- .../WriteOnlyPropertyInspection.cs | 16 ++++----- RetailCoder.VBE/Root/RubberduckModule.cs | 2 +- .../InspectionResultsControl.xaml | 7 ++-- .../InspectionResultsViewModel.cs | 23 ++++++++++--- RetailCoder.VBE/UI/Command/CommandBase.cs | 10 ++---- RetailCoder.VBE/UI/Command/DelegateCommand.cs | 11 +----- 38 files changed, 318 insertions(+), 330 deletions(-) diff --git a/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs b/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs index 48d4e89f2b..05491a7002 100644 --- a/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs +++ b/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs @@ -1,6 +1,5 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; @@ -8,27 +7,21 @@ namespace Rubberduck.Inspections { - public class AssignedByValParameterInspection : IInspection + public sealed class AssignedByValParameterInspection : InspectionBase { - public AssignedByValParameterInspection() + public AssignedByValParameterInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "AssignedByValParameterInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ByValParameterIsAssigned_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ByValParameterIsAssigned_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - private string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var name = AnnotationName; - var assignedByValParameters = - state.AllUserDeclarations.Where(declaration => !declaration.IsInspectionDisabled(name) - && declaration.DeclarationType == DeclarationType.Parameter + var assignedByValParameters = UserDeclarations.Where(declaration => + declaration.DeclarationType == DeclarationType.Parameter && ((VBAParser.ArgContext)declaration.Context).BYVAL() != null && declaration.References.Any(reference => reference.IsAssignment)); diff --git a/RetailCoder.VBE/Inspections/ConstantNotUsedInspection.cs b/RetailCoder.VBE/Inspections/ConstantNotUsedInspection.cs index 48d570c1ba..3c47df7c9d 100644 --- a/RetailCoder.VBE/Inspections/ConstantNotUsedInspection.cs +++ b/RetailCoder.VBE/Inspections/ConstantNotUsedInspection.cs @@ -6,22 +6,20 @@ namespace Rubberduck.Inspections { - public class ConstantNotUsedInspection : IInspection + public sealed class ConstantNotUsedInspection : InspectionBase { - public ConstantNotUsedInspection() + public ConstantNotUsedInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ConstantNotUsedInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ConstantNotUsed_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ConstantNotUsed_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var results = state.AllUserDeclarations.Where(declaration => + var results = UserDeclarations.Where(declaration => declaration.DeclarationType == DeclarationType.Constant && !declaration.References.Any()); return results.Select(issue => diff --git a/RetailCoder.VBE/Inspections/DefaultProjectNameInspection.cs b/RetailCoder.VBE/Inspections/DefaultProjectNameInspection.cs index ed31b8442c..f2aa31327e 100644 --- a/RetailCoder.VBE/Inspections/DefaultProjectNameInspection.cs +++ b/RetailCoder.VBE/Inspections/DefaultProjectNameInspection.cs @@ -7,28 +7,26 @@ namespace Rubberduck.Inspections { - public class DefaultProjectNameInspection : IInspection + public sealed class DefaultProjectNameInspection : InspectionBase { private readonly ICodePaneWrapperFactory _wrapperFactory; - public DefaultProjectNameInspection() + public DefaultProjectNameInspection(RubberduckParserState state) + : base(state) { _wrapperFactory = new CodePaneWrapperFactory(); Severity = CodeInspectionSeverity.Suggestion; } - public string Name { get { return "DefaultProjectNameInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.GenericProjectName_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.GenericProjectName_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var issues = state.AllUserDeclarations + var issues = UserDeclarations .Where(declaration => declaration.DeclarationType == DeclarationType.Project && declaration.IdentifierName.StartsWith("VBAProject")) - .Select(issue => new DefaultProjectNameInspectionResult(this, issue, state, _wrapperFactory)) + .Select(issue => new DefaultProjectNameInspectionResult(this, issue, State, _wrapperFactory)) .ToList(); return issues; diff --git a/RetailCoder.VBE/Inspections/EmptyStringLiteralInspection.cs b/RetailCoder.VBE/Inspections/EmptyStringLiteralInspection.cs index 543e72ffd3..71a93832f7 100644 --- a/RetailCoder.VBE/Inspections/EmptyStringLiteralInspection.cs +++ b/RetailCoder.VBE/Inspections/EmptyStringLiteralInspection.cs @@ -6,25 +6,21 @@ namespace Rubberduck.Inspections { - public class EmptyStringLiteralInspection : IInspection + public sealed class EmptyStringLiteralInspection : InspectionBase { - public EmptyStringLiteralInspection() + public EmptyStringLiteralInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "EmptyStringLiteralInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return InspectionsUI.EmptyStringLiteralInspection; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return InspectionsUI.EmptyStringLiteralInspection; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) - { - return - state.EmptyStringLiterals.Select( - context => - new EmptyStringLiteralInspectionResult(this, + public override IEnumerable GetInspectionResults() + { + return State.EmptyStringLiterals.Select( + context => new EmptyStringLiteralInspectionResult(this, new QualifiedContext(context.ModuleName, context.Context))); } } diff --git a/RetailCoder.VBE/Inspections/IInspection.cs b/RetailCoder.VBE/Inspections/IInspection.cs index cd51a37b1f..2ee55c372e 100644 --- a/RetailCoder.VBE/Inspections/IInspection.cs +++ b/RetailCoder.VBE/Inspections/IInspection.cs @@ -1,4 +1,6 @@ using System.Collections.Generic; +using System.Linq; +using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; namespace Rubberduck.Inspections @@ -12,11 +14,41 @@ public interface IInspection : IInspectionModel /// Runs code inspection on specified parse trees. /// /// Returns inspection results, if any. - IEnumerable GetInspectionResults(RubberduckParserState state); + IEnumerable GetInspectionResults(); /// /// Gets a string that contains additional/meta information about an inspection. /// string Meta { get; } + + } + + public abstract class InspectionBase : IInspection + { + protected readonly RubberduckParserState State; + protected InspectionBase(RubberduckParserState state) + { + State = state; + } + + public abstract string Description { get; } + public abstract CodeInspectionType InspectionType { get; } + public abstract IEnumerable GetInspectionResults(); + + public virtual string Name { get { return GetType().Name; } } + public virtual CodeInspectionSeverity Severity { get; set; } + public virtual string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } + public virtual string InspectionTypeName { get { return InspectionsUI.ResourceManager.GetString(InspectionType.ToString()); } } + protected virtual string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } + + protected virtual IEnumerable Declarations + { + get { return State.AllDeclarations.Where(declaration => !declaration.IsInspectionDisabled(AnnotationName)); } + } + + protected virtual IEnumerable UserDeclarations + { + get { return State.AllUserDeclarations.Where(declaration => !declaration.IsInspectionDisabled(AnnotationName)); } + } } } diff --git a/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs b/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs index 545f556648..96e68e42d1 100644 --- a/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs +++ b/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs @@ -11,28 +11,26 @@ namespace Rubberduck.Inspections { - public class ImplicitActiveSheetReferenceInspection : IInspection + public sealed class ImplicitActiveSheetReferenceInspection : InspectionBase { private readonly Func _hostApp; - public ImplicitActiveSheetReferenceInspection(VBE vbe) + public ImplicitActiveSheetReferenceInspection(VBE vbe, RubberduckParserState state) + : base(state) { _hostApp = vbe.HostApplication; Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ImplicitActiveSheetReferenceInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ImplicitActiveSheetReference_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ImplicitActiveSheetReference_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } private static readonly string[] Targets = { "Cells", "Range", "Columns", "Rows" }; - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { if (_hostApp().ApplicationName != "Excel") { @@ -40,7 +38,7 @@ public IEnumerable GetInspectionResults(RubberduckPars // if host isn't Excel, the ExcelObjectModel declarations shouldn't be loaded anyway. } - var issues = state.AllDeclarations.Where(item => item.IsBuiltIn + var issues = Declarations.Where(item => item.IsBuiltIn && item.ParentScope == "Excel.Global" && Targets.Contains(item.IdentifierName) && item.References.Any()) diff --git a/RetailCoder.VBE/Inspections/ImplicitActiveWorkbookReferenceInspection.cs b/RetailCoder.VBE/Inspections/ImplicitActiveWorkbookReferenceInspection.cs index 116f895eec..40203211f8 100644 --- a/RetailCoder.VBE/Inspections/ImplicitActiveWorkbookReferenceInspection.cs +++ b/RetailCoder.VBE/Inspections/ImplicitActiveWorkbookReferenceInspection.cs @@ -9,28 +9,26 @@ namespace Rubberduck.Inspections { - public class ImplicitActiveWorkbookReferenceInspection : IInspection + public sealed class ImplicitActiveWorkbookReferenceInspection : InspectionBase { private readonly Lazy _hostApp; - public ImplicitActiveWorkbookReferenceInspection(VBE vbe) + public ImplicitActiveWorkbookReferenceInspection(VBE vbe, RubberduckParserState state) + : base(state) { _hostApp = new Lazy(vbe.HostApplication); Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ImplicitActiveWorkbookReferenceInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ImplicitActiveWorkbookReference_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ImplicitActiveWorkbookReference_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } private static readonly string[] Targets = { "Worksheets", "Sheets", "Names", }; - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { if (!_hostApp.IsValueCreated || _hostApp.Value == null || _hostApp.Value.ApplicationName != "Excel") { @@ -38,10 +36,10 @@ public IEnumerable GetInspectionResults(RubberduckPars // if host isn't Excel, the ExcelObjectModel declarations shouldn't be loaded anyway. } - var issues = state.AllDeclarations.Where(item => item.IsBuiltIn - && item.ParentScope == "Excel.Global" - && Targets.Contains(item.IdentifierName) - && item.References.Any()) + var issues = Declarations.Where(item => item.IsBuiltIn + && item.ParentScope == "Excel.Global" + && Targets.Contains(item.IdentifierName) + && item.References.Any()) .SelectMany(declaration => declaration.References); return issues.Select(issue => diff --git a/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspection.cs b/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspection.cs index dbda9962d1..6e93554e60 100644 --- a/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspection.cs +++ b/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspection.cs @@ -9,28 +9,22 @@ namespace Rubberduck.Inspections { - public class ImplicitByRefParameterInspection : IInspection + public sealed class ImplicitByRefParameterInspection : InspectionBase { - public ImplicitByRefParameterInspection() + public ImplicitByRefParameterInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ImplicitByRefParameterInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ImplicitByRef_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ImplicitByRef_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - private string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllUserDeclarations.ToList(); - - var interfaceMembers = declarations.FindInterfaceImplementationMembers(); + var interfaceMembers = UserDeclarations.FindInterfaceImplementationMembers(); - var issues = (from item in declarations + var issues = (from item in UserDeclarations where !item.IsInspectionDisabled(AnnotationName) && item.DeclarationType == DeclarationType.Parameter && !interfaceMembers.Select(m => m.Scope).Contains(item.ParentScope) @@ -39,6 +33,7 @@ public IEnumerable GetInspectionResults(RubberduckPars select new QualifiedContext(item.QualifiedName, arg)) .Select(issue => new ImplicitByRefParameterInspectionResult(this, string.Format(Description, issue.Context.ambiguousIdentifier().GetText()), issue)); + return issues; } } diff --git a/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspection.cs b/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspection.cs index e5ae30731a..7f72021a06 100644 --- a/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspection.cs +++ b/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspection.cs @@ -8,18 +8,16 @@ namespace Rubberduck.Inspections { - public class ImplicitPublicMemberInspection : IInspection + public sealed class ImplicitPublicMemberInspection : InspectionBase { - public ImplicitPublicMemberInspection() + public ImplicitPublicMemberInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ImplicitPublicMemberInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ImplicitPublicMember_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ImplicitPublicMember_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } private static readonly DeclarationType[] ProcedureTypes = { @@ -30,11 +28,9 @@ public ImplicitPublicMemberInspection() DeclarationType.PropertySet }; - private string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var issues = from item in state.AllUserDeclarations + var issues = from item in UserDeclarations where !item.IsInspectionDisabled(AnnotationName) && ProcedureTypes.Contains(item.DeclarationType) && item.Accessibility == Accessibility.Implicit diff --git a/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspection.cs b/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspection.cs index 46bfbee76f..7a6c65b753 100644 --- a/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspection.cs +++ b/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspection.cs @@ -8,18 +8,16 @@ namespace Rubberduck.Inspections { - public class ImplicitVariantReturnTypeInspection : IInspection + public sealed class ImplicitVariantReturnTypeInspection : InspectionBase { - public ImplicitVariantReturnTypeInspection() + public ImplicitVariantReturnTypeInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ImplicitVariantReturnTypeInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ImplicitVariantReturnType_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ImplicitVariantReturnType_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } private static readonly DeclarationType[] ProcedureTypes = { @@ -28,11 +26,9 @@ public ImplicitVariantReturnTypeInspection() DeclarationType.LibraryFunction }; - private string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var issues = from item in state.AllUserDeclarations + var issues = from item in UserDeclarations where !item.IsInspectionDisabled(AnnotationName) && ProcedureTypes.Contains(item.DeclarationType) && !item.IsTypeSpecified() diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs index 57e6a3c879..f87dd36000 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs +++ b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs @@ -78,6 +78,15 @@ internal static string AssignedByValParameterInspectionName { } } + /// + /// Looks up a localized string similar to Code quality issues. + /// + internal static string CodeQualityIssues { + get { + return ResourceManager.GetString("CodeQualityIssues", resourceCulture); + } + } + /// /// Looks up a localized string similar to Constant value is declared but Rubberduck could not find any reference to it. Consider removing the unused declaration.. /// @@ -240,6 +249,24 @@ internal static string ImplicitVariantReturnTypeInspectionName { } } + /// + /// Looks up a localized string similar to Language opportunities. + /// + internal static string LanguageOpportunities { + get { + return ResourceManager.GetString("LanguageOpportunities", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Maintainability & readability issues. + /// + internal static string MaintainabilityAndReadabilityIssues { + get { + return ResourceManager.GetString("MaintainabilityAndReadabilityIssues", resourceCulture); + } + } + /// /// Looks up a localized string similar to Consider continuing long signatures between parameters. Splitting a parameter declaration across multiple lines arguably hurts readability.. /// @@ -432,9 +459,9 @@ internal static string ParameterCanBeByValInspectionMeta { /// /// Looks up a localized string similar to Parameter can be passed by value. /// - internal static string ParameterCanByByValInspectionName { + internal static string ParameterCanBeByValInspectionName { get { - return ResourceManager.GetString("ParameterCanByByValInspectionName", resourceCulture); + return ResourceManager.GetString("ParameterCanBeByValInspectionName", resourceCulture); } } diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.resx b/RetailCoder.VBE/Inspections/InspectionsUI.resx index 2931a2ebaf..1b0d6a3094 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.resx +++ b/RetailCoder.VBE/Inspections/InspectionsUI.resx @@ -123,6 +123,9 @@ ByVal parameter is assigned + + Code quality issues + Constant value is declared but Rubberduck could not find any reference to it. Consider removing the unused declaration. @@ -177,6 +180,12 @@ Return type is implicitly 'Variant' + + Language opportunities + + + Maintainability & readability issues + Consider continuing long signatures between parameters. Splitting a parameter declaration across multiple lines arguably hurts readability. @@ -240,7 +249,7 @@ A parameter that is passed by reference but that isn't assigned a new value/reference, could be passed by value instead. - + Parameter can be passed by value diff --git a/RetailCoder.VBE/Inspections/Inspector.cs b/RetailCoder.VBE/Inspections/Inspector.cs index ebb10fe37a..9373df924f 100644 --- a/RetailCoder.VBE/Inspections/Inspector.cs +++ b/RetailCoder.VBE/Inspections/Inspector.cs @@ -68,7 +68,7 @@ public async Task> FindIssuesAsync(RubberduckParser new Task(() => { token.ThrowIfCancellationRequested(); - var inspectionResults = inspection.GetInspectionResults(state); + var inspectionResults = inspection.GetInspectionResults(); var results = inspectionResults as IList ?? inspectionResults.ToList(); if (results.Any()) diff --git a/RetailCoder.VBE/Inspections/MultilineParameterInspection.cs b/RetailCoder.VBE/Inspections/MultilineParameterInspection.cs index e4c8dd92cf..a69ad04ecf 100644 --- a/RetailCoder.VBE/Inspections/MultilineParameterInspection.cs +++ b/RetailCoder.VBE/Inspections/MultilineParameterInspection.cs @@ -7,22 +7,20 @@ namespace Rubberduck.Inspections { - public class MultilineParameterInspection : IInspection + public sealed class MultilineParameterInspection : InspectionBase { - public MultilineParameterInspection() + public MultilineParameterInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "MultilineParameterInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.MultilineParameter_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.MultilineParameter_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var multilineParameters = from p in state.AllUserDeclarations + var multilineParameters = from p in UserDeclarations .Where(item => item.DeclarationType == DeclarationType.Parameter) where p.Context.GetSelection().LineCount > 1 select p; diff --git a/RetailCoder.VBE/Inspections/MultipleDeclarationsInspection.cs b/RetailCoder.VBE/Inspections/MultipleDeclarationsInspection.cs index b747a2bcd9..16cc7eec1f 100644 --- a/RetailCoder.VBE/Inspections/MultipleDeclarationsInspection.cs +++ b/RetailCoder.VBE/Inspections/MultipleDeclarationsInspection.cs @@ -8,24 +8,20 @@ namespace Rubberduck.Inspections { - public class MultipleDeclarationsInspection : IInspection + public sealed class MultipleDeclarationsInspection : InspectionBase { - public MultipleDeclarationsInspection() + public MultipleDeclarationsInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "MultipleDeclarationsInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.MultipleDeclarations; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.MultipleDeclarations; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - private string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var issues = state.AllUserDeclarations + var issues = UserDeclarations .Where(item => !item.IsInspectionDisabled(AnnotationName)) .Where(item => item.DeclarationType == DeclarationType.Variable || item.DeclarationType == DeclarationType.Constant) diff --git a/RetailCoder.VBE/Inspections/NonReturningFunctionInspection.cs b/RetailCoder.VBE/Inspections/NonReturningFunctionInspection.cs index 071e5c4a98..395210de09 100644 --- a/RetailCoder.VBE/Inspections/NonReturningFunctionInspection.cs +++ b/RetailCoder.VBE/Inspections/NonReturningFunctionInspection.cs @@ -9,18 +9,16 @@ namespace Rubberduck.Inspections { - public class NonReturningFunctionInspection : IInspection + public sealed class NonReturningFunctionInspection : InspectionBase { - public NonReturningFunctionInspection() + public NonReturningFunctionInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "NonReturningFunctionInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.NonReturningFunction_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.NonReturningFunction_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } private static readonly DeclarationType[] ReturningMemberTypes = { @@ -28,9 +26,9 @@ public NonReturningFunctionInspection() DeclarationType.PropertyGet }; - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllUserDeclarations.ToList(); + var declarations = UserDeclarations.ToList(); var interfaceMembers = declarations.FindInterfaceMembers(); var interfaceImplementationMembers = declarations.FindInterfaceImplementationMembers(); diff --git a/RetailCoder.VBE/Inspections/ObsoleteCallStatementInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteCallStatementInspection.cs index 8a3699d70b..2656e4698f 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteCallStatementInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteCallStatementInspection.cs @@ -7,22 +7,20 @@ namespace Rubberduck.Inspections { - public class ObsoleteCallStatementInspection : IInspection + public sealed class ObsoleteCallStatementInspection : InspectionBase { - public ObsoleteCallStatementInspection() + public ObsoleteCallStatementInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Suggestion; } - public string Name { get { return "ObsoleteCallStatementInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ObsoleteCall; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ObsoleteCall; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - return state.ObsoleteCallContexts.Select(context => + return State.ObsoleteCallContexts.Select(context => new ObsoleteCallStatementUsageInspectionResult(this, new QualifiedContext(context.ModuleName, context.Context as VBAParser.ExplicitCallStmtContext))); } diff --git a/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs index 802d77d795..9fd5fd23d2 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspection.cs @@ -6,26 +6,24 @@ namespace Rubberduck.Inspections { - public class ObsoleteCommentSyntaxInspection : IInspection + public sealed class ObsoleteCommentSyntaxInspection : InspectionBase { /// /// Parameterless constructor required for discovery of implemented code inspections. /// - public ObsoleteCommentSyntaxInspection() + public ObsoleteCommentSyntaxInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Suggestion; } - public string Name { get { return "ObsoleteCommentSyntaxInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ObsoleteComment; } } - public CodeInspectionType InspectionType { get {return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ObsoleteComment; } } + public override CodeInspectionType InspectionType { get {return CodeInspectionType.LanguageOpportunities; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - return (state.AllComments.Where(comment => comment.Marker == Tokens.Rem) - .Select(comment => new ObsoleteCommentSyntaxInspectionResult(this, comment))); + return State.AllComments.Where(comment => comment.Marker == Tokens.Rem) + .Select(comment => new ObsoleteCommentSyntaxInspectionResult(this, comment)); } } } \ No newline at end of file diff --git a/RetailCoder.VBE/Inspections/ObsoleteGlobalInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteGlobalInspection.cs index 19d64c7e91..2ff35b015f 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteGlobalInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteGlobalInspection.cs @@ -8,22 +8,20 @@ namespace Rubberduck.Inspections { - public class ObsoleteGlobalInspection : IInspection + public sealed class ObsoleteGlobalInspection : InspectionBase { - public ObsoleteGlobalInspection() + public ObsoleteGlobalInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Suggestion; } - public string Name { get { return "ObsoleteGlobalInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ObsoleteGlobal; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ObsoleteGlobal; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var issues = from item in state.AllUserDeclarations + var issues = from item in UserDeclarations where item.Accessibility == Accessibility.Global && item.Context != null select new ObsoleteGlobalInspectionResult(this, Description, new QualifiedContext(item.QualifiedName.QualifiedModuleName, item.Context)); diff --git a/RetailCoder.VBE/Inspections/ObsoleteLetStatementInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteLetStatementInspection.cs index 9595a081cc..e9481cb7ea 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteLetStatementInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteLetStatementInspection.cs @@ -7,22 +7,20 @@ namespace Rubberduck.Inspections { - public class ObsoleteLetStatementInspection : IInspection + public sealed class ObsoleteLetStatementInspection : InspectionBase { - public ObsoleteLetStatementInspection() + public ObsoleteLetStatementInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Suggestion; } - public string Name { get { return "ObsoleteLetStatementInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ObsoleteLet; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ObsoleteLet; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - return state.ObsoleteLetContexts.Select(context => + return State.ObsoleteLetContexts.Select(context => new ObsoleteLetStatementUsageInspectionResult(this, new QualifiedContext(context.ModuleName, context.Context))); } } diff --git a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs index 5d335ad40a..9dd41d50df 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs @@ -6,22 +6,20 @@ namespace Rubberduck.Inspections { - public class ObsoleteTypeHintInspection : IInspection + public sealed class ObsoleteTypeHintInspection : InspectionBase { - public ObsoleteTypeHintInspection() + public ObsoleteTypeHintInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Suggestion; } - public string Name { get { return "ObsoleteTypeHintInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI._ObsoleteTypeHint_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI._ObsoleteTypeHint_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var results = state.AllUserDeclarations.ToList(); + var results = UserDeclarations.ToList(); var declarations = from item in results where item.HasTypeHint() diff --git a/RetailCoder.VBE/Inspections/OptionBaseInspection.cs b/RetailCoder.VBE/Inspections/OptionBaseInspection.cs index 40ccc7c6e8..f6e24c85cc 100644 --- a/RetailCoder.VBE/Inspections/OptionBaseInspection.cs +++ b/RetailCoder.VBE/Inspections/OptionBaseInspection.cs @@ -8,29 +8,24 @@ namespace Rubberduck.Inspections { - public class OptionBaseInspection : IInspection + public sealed class OptionBaseInspection : InspectionBase { private readonly ICodePaneWrapperFactory _wrapperFactory; - public OptionBaseInspection() + public OptionBaseInspection(RubberduckParserState state) + : base(state) { _wrapperFactory = new CodePaneWrapperFactory(); Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "OptionBaseInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.OptionBase; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.OptionBase; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - private string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var options = state.AllUserDeclarations - .Where(declaration => !declaration.IsInspectionDisabled(AnnotationName) - && declaration.DeclarationType == DeclarationType.ModuleOption + var options = UserDeclarations + .Where(declaration => declaration.DeclarationType == DeclarationType.ModuleOption && declaration.Context is VBAParser.OptionBaseStmtContext) .ToList(); diff --git a/RetailCoder.VBE/Inspections/OptionExplicitInspection.cs b/RetailCoder.VBE/Inspections/OptionExplicitInspection.cs index af5dea436f..e6f3bc339a 100644 --- a/RetailCoder.VBE/Inspections/OptionExplicitInspection.cs +++ b/RetailCoder.VBE/Inspections/OptionExplicitInspection.cs @@ -7,18 +7,16 @@ namespace Rubberduck.Inspections { - public class OptionExplicitInspection : IInspection + public sealed class OptionExplicitInspection : InspectionBase { - public OptionExplicitInspection() + public OptionExplicitInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "OptionExplicitInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.OptionExplicit; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.OptionExplicit; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } private static readonly DeclarationType[] ModuleTypes = { @@ -26,9 +24,9 @@ public OptionExplicitInspection() DeclarationType.Class }; - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var results = state.AllUserDeclarations.ToList(); + var results = UserDeclarations.ToList(); var options = results .Where(declaration => declaration.DeclarationType == DeclarationType.ModuleOption diff --git a/RetailCoder.VBE/Inspections/ParameterCanBeByValInspection.cs b/RetailCoder.VBE/Inspections/ParameterCanBeByValInspection.cs index a29478d2b1..dad3d1941d 100644 --- a/RetailCoder.VBE/Inspections/ParameterCanBeByValInspection.cs +++ b/RetailCoder.VBE/Inspections/ParameterCanBeByValInspection.cs @@ -8,18 +8,16 @@ namespace Rubberduck.Inspections { - public class ParameterCanBeByValInspection : IInspection + public sealed class ParameterCanBeByValInspection : InspectionBase { - public ParameterCanBeByValInspection() + public ParameterCanBeByValInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { { return "ParameterCanBeByValInspection"; } } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ParameterCanBeByVal_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ParameterCanBeByVal_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } // if we don't want to suggest passing non-primitive types ByRef (i.e. object types and Variant), then we need this: private static readonly string[] PrimitiveTypes = @@ -38,9 +36,9 @@ public ParameterCanBeByValInspection() Tokens.StrPtr }; - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllDeclarations.ToList(); + var declarations = UserDeclarations.ToList(); var interfaceMembers = declarations.FindInterfaceMembers() .Concat(declarations.FindInterfaceImplementationMembers()) diff --git a/RetailCoder.VBE/Inspections/ParameterNotUsedInspection.cs b/RetailCoder.VBE/Inspections/ParameterNotUsedInspection.cs index 8155824b92..3173f10de3 100644 --- a/RetailCoder.VBE/Inspections/ParameterNotUsedInspection.cs +++ b/RetailCoder.VBE/Inspections/ParameterNotUsedInspection.cs @@ -13,13 +13,14 @@ namespace Rubberduck.Inspections { - public class ParameterNotUsedInspection : IInspection + public sealed class ParameterNotUsedInspection : InspectionBase { private readonly VBE _vbe; private readonly IMessageBox _messageBox; private readonly ICodePaneWrapperFactory _wrapperFactory; - public ParameterNotUsedInspection(VBE vbe, IMessageBox messageBox) + public ParameterNotUsedInspection(VBE vbe, RubberduckParserState state, IMessageBox messageBox) + : base(state) { _vbe = vbe; // todo: remove this dependency _messageBox = messageBox; @@ -27,15 +28,12 @@ public ParameterNotUsedInspection(VBE vbe, IMessageBox messageBox) Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ParameterNotUsedInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ParameterNotUsed_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ParameterNotUsed_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllDeclarations.ToList(); + var declarations = UserDeclarations.ToList(); var interfaceMemberScopes = declarations.FindInterfaceMembers().Select(m => m.Scope).ToList(); var interfaceImplementationMemberScopes = declarations.FindInterfaceImplementationMembers().Select(m => m.Scope).ToList(); @@ -50,11 +48,11 @@ public IEnumerable GetInspectionResults(RubberduckPars var quickFixRefactoring = new RemoveParametersRefactoring( new RemoveParametersPresenterFactory(editor, - new RemoveParametersDialog(), state, _messageBox), editor); + new RemoveParametersDialog(), State, _messageBox), editor); var issues = from issue in unused.Where(parameter => !IsInterfaceMemberParameter(parameter, interfaceMemberScopes)) let isInterfaceImplementationMember = IsInterfaceMemberImplementationParameter(issue, interfaceImplementationMemberScopes) - select new ParameterNotUsedInspectionResult(this, string.Format(Description, issue.IdentifierName), ((dynamic)issue.Context).ambiguousIdentifier(), issue.QualifiedName, isInterfaceImplementationMember, quickFixRefactoring, state); + select new ParameterNotUsedInspectionResult(this, string.Format(Description, issue.IdentifierName), ((dynamic)issue.Context).ambiguousIdentifier(), issue.QualifiedName, isInterfaceImplementationMember, quickFixRefactoring, State); return issues.ToList(); } diff --git a/RetailCoder.VBE/Inspections/ProcedureNotUsedInspection.cs b/RetailCoder.VBE/Inspections/ProcedureNotUsedInspection.cs index 7dabd0c820..07fa1e3fc9 100644 --- a/RetailCoder.VBE/Inspections/ProcedureNotUsedInspection.cs +++ b/RetailCoder.VBE/Inspections/ProcedureNotUsedInspection.cs @@ -10,22 +10,20 @@ namespace Rubberduck.Inspections { - public class ProcedureNotUsedInspection : IInspection + public sealed class ProcedureNotUsedInspection : InspectionBase { - public ProcedureNotUsedInspection() + public ProcedureNotUsedInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "ProcedureNotUsedInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.ProcedureNotUsed_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.ProcedureNotUsed_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllUserDeclarations.ToList(); + var declarations = UserDeclarations.ToList(); var classes = declarations.Where(item => item.DeclarationType == DeclarationType.Class).ToList(); var modules = declarations.Where(item => item.DeclarationType == DeclarationType.Module).ToList(); diff --git a/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs b/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs index 14d00942fd..39a10b5686 100644 --- a/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs +++ b/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs @@ -1,37 +1,33 @@ using System.Collections.Generic; using System.Linq; -using Rubberduck.Parsing; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.UI; namespace Rubberduck.Inspections { - public class UnassignedVariableUsageInspection //: IInspection // disabled + public sealed class UnassignedVariableUsageInspection : InspectionBase { - public UnassignedVariableUsageInspection() + public UnassignedVariableUsageInspection(RubberduckParserState state) + : base(state) { - Severity = CodeInspectionSeverity.Warning; + Severity = CodeInspectionSeverity.Error; } - public string Name { get { return RubberduckUI.UnassignedVariableUsage_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } + public override string Description { get { return RubberduckUI.UnassignedVariableUsage_; } } - public IEnumerable GetInspectionResults(RubberduckParserState parseResult) + public override IEnumerable GetInspectionResults() { - var usages = parseResult.AllUserDeclarations.Where(declaration => + var usages = UserDeclarations.Where(declaration => declaration.DeclarationType == DeclarationType.Variable && !declaration.References.Any(reference => reference.IsAssignment)) .SelectMany(declaration => declaration.References); foreach (var issue in usages) { - //todo: add context to IdentifierReference - //yield return new UnassignedVariableUsageInspectionResult(string.Format(Name, issue.Context.GetText()), Severity, issue.Context, issue.QualifiedName); + yield return new UnassignedVariableUsageInspectionResult(this, string.Format(Name, issue.Context.GetText()), issue.Context, issue.QualifiedModuleName); } - - return null; } } } \ No newline at end of file diff --git a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspection.cs b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspection.cs index 90256e364e..f1c4071363 100644 --- a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspection.cs +++ b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspection.cs @@ -7,18 +7,16 @@ namespace Rubberduck.Inspections { - public class UntypedFunctionUsageInspection : IInspection + public sealed class UntypedFunctionUsageInspection : InspectionBase { - public UntypedFunctionUsageInspection() + public UntypedFunctionUsageInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Hint; } - public string Name { get { return "UntypedFunctionUsageInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.UntypedFunctionUsage_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.UntypedFunctionUsage_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } private readonly string[] _tokens = { Tokens.Error, @@ -44,9 +42,9 @@ public UntypedFunctionUsageInspection() Tokens.UCase }; - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllDeclarations + var declarations = UserDeclarations .Where(item => item.IsBuiltIn && item.Accessibility == Accessibility.Global && _tokens.Contains(item.IdentifierName)); return declarations.SelectMany(declaration => declaration.References diff --git a/RetailCoder.VBE/Inspections/UseMeaningfulNameInspection.cs b/RetailCoder.VBE/Inspections/UseMeaningfulNameInspection.cs index a1fe10dad3..9469b5ae9d 100644 --- a/RetailCoder.VBE/Inspections/UseMeaningfulNameInspection.cs +++ b/RetailCoder.VBE/Inspections/UseMeaningfulNameInspection.cs @@ -6,31 +6,29 @@ namespace Rubberduck.Inspections { - public class UseMeaningfulNameInspection : IInspection + public sealed class UseMeaningfulNameInspection : InspectionBase { private readonly IMessageBox _messageBox; private readonly ICodePaneWrapperFactory _wrapperFactory; - public UseMeaningfulNameInspection(IMessageBox messageBox) + public UseMeaningfulNameInspection(IMessageBox messageBox, RubberduckParserState state) + : base(state) { _messageBox = messageBox; _wrapperFactory = new CodePaneWrapperFactory(); Severity = CodeInspectionSeverity.Suggestion; } - public string Name { get { return "UseMeaningfulNameInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return InspectionsUI.UseMeaningfulNameInspection; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return InspectionsUI.UseMeaningfulNameInspection; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var issues = state.AllUserDeclarations + var issues = UserDeclarations .Where(declaration => declaration.IdentifierName.Length < 3 || char.IsDigit(declaration.IdentifierName.Last()) || !declaration.IdentifierName.Any(c => new[] {'a', 'e', 'i', 'o', 'u', 'y'}.Contains(c))) - .Select(issue => new UseMeaningfulNameInspectionResult(this, issue, state, _wrapperFactory, _messageBox)) + .Select(issue => new UseMeaningfulNameInspectionResult(this, issue, State, _wrapperFactory, _messageBox)) .ToList(); return issues; diff --git a/RetailCoder.VBE/Inspections/VariableNotAssignedInspection.cs b/RetailCoder.VBE/Inspections/VariableNotAssignedInspection.cs index 9f5562d7bb..81f4a9af06 100644 --- a/RetailCoder.VBE/Inspections/VariableNotAssignedInspection.cs +++ b/RetailCoder.VBE/Inspections/VariableNotAssignedInspection.cs @@ -6,22 +6,20 @@ namespace Rubberduck.Inspections { - public class VariableNotAssignedInspection : IInspection + public sealed class VariableNotAssignedInspection : InspectionBase { - public VariableNotAssignedInspection() + public VariableNotAssignedInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "VariableNotAssignedInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.VariableNotAssigned_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.VariableNotAssigned_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var items = state.AllUserDeclarations.ToList(); + var items = UserDeclarations.ToList(); // ignore arrays. todo: ArrayIndicesNotAccessedInspection var arrays = items.Where(declaration => diff --git a/RetailCoder.VBE/Inspections/VariableNotUsedInspection.cs b/RetailCoder.VBE/Inspections/VariableNotUsedInspection.cs index 872550f491..2ed70f51cf 100644 --- a/RetailCoder.VBE/Inspections/VariableNotUsedInspection.cs +++ b/RetailCoder.VBE/Inspections/VariableNotUsedInspection.cs @@ -6,22 +6,20 @@ namespace Rubberduck.Inspections { - public class VariableNotUsedInspection : IInspection + public sealed class VariableNotUsedInspection : InspectionBase { - public VariableNotUsedInspection() + public VariableNotUsedInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "VariableNotUsedInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.VariableNotUsed_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.VariableNotUsed_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllUserDeclarations.Where(declaration => + var declarations = UserDeclarations.Where(declaration => !declaration.IsWithEvents && declaration.DeclarationType == DeclarationType.Variable && declaration.References.All(reference => reference.IsAssignment)); diff --git a/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspection.cs b/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspection.cs index 3b88e2ad1c..f3b23f6d7b 100644 --- a/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspection.cs +++ b/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspection.cs @@ -6,22 +6,20 @@ namespace Rubberduck.Inspections { - public class VariableTypeNotDeclaredInspection : IInspection + public sealed class VariableTypeNotDeclaredInspection : InspectionBase { - public VariableTypeNotDeclaredInspection() + public VariableTypeNotDeclaredInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "VariableTypeNotDeclaredInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI._TypeNotDeclared_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI._TypeNotDeclared_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.LanguageOpportunities; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var issues = from item in state.AllUserDeclarations + var issues = from item in UserDeclarations where (item.DeclarationType == DeclarationType.Variable || item.DeclarationType == DeclarationType.Constant || item.DeclarationType == DeclarationType.Parameter) diff --git a/RetailCoder.VBE/Inspections/WriteOnlyPropertyInspection.cs b/RetailCoder.VBE/Inspections/WriteOnlyPropertyInspection.cs index ce7195f2d3..5cc6f4cae4 100644 --- a/RetailCoder.VBE/Inspections/WriteOnlyPropertyInspection.cs +++ b/RetailCoder.VBE/Inspections/WriteOnlyPropertyInspection.cs @@ -6,22 +6,20 @@ namespace Rubberduck.Inspections { - public class WriteOnlyPropertyInspection : IInspection + public sealed class WriteOnlyPropertyInspection : InspectionBase { - public WriteOnlyPropertyInspection() + public WriteOnlyPropertyInspection(RubberduckParserState state) + : base(state) { Severity = CodeInspectionSeverity.Warning; } - public string Name { get { return "WriteOnlyPropertyInspection"; } } - public string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public string Description { get { return RubberduckUI.WriteOnlyProperty_; } } - public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public CodeInspectionSeverity Severity { get; set; } + public override string Description { get { return RubberduckUI.WriteOnlyProperty_; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } - public IEnumerable GetInspectionResults(RubberduckParserState state) + public override IEnumerable GetInspectionResults() { - var declarations = state.AllUserDeclarations.ToList(); + var declarations = UserDeclarations.ToList(); var setters = declarations .Where(item => (item.Accessibility == Accessibility.Implicit || diff --git a/RetailCoder.VBE/Root/RubberduckModule.cs b/RetailCoder.VBE/Root/RubberduckModule.cs index 9c002d7950..5dfb9d3741 100644 --- a/RetailCoder.VBE/Root/RubberduckModule.cs +++ b/RetailCoder.VBE/Root/RubberduckModule.cs @@ -129,7 +129,7 @@ private void BindCodeInspectionTypes() { var inspections = Assembly.GetExecutingAssembly() .GetTypes() - .Where(type => type.GetInterfaces().Contains(typeof (IInspection))); + .Where(type => type.BaseType == typeof (InspectionBase)); // multibinding for IEnumerable dependency foreach (var inspection in inspections) diff --git a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml index 0ea4337064..8e2c114fd4 100644 --- a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml +++ b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml @@ -89,7 +89,7 @@ - + @@ -190,7 +190,7 @@ - @@ -198,8 +198,7 @@ + ItemsSource="{Binding SelectedItem.QuickFixes}"> diff --git a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs index 25a0462329..83e15e7e9c 100644 --- a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs +++ b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs @@ -33,12 +33,12 @@ public InspectionResultsViewModel(RubberduckParserState state, IInspector inspec _navigateCommand = navigateCommand; _clipboard = clipboard; _configService = configService; - _refreshCommand = new DelegateCommand(async param => await Task.Run(() => ExecuteRefreshCommandAsync(param))); + _refreshCommand = new DelegateCommand(async param => await Task.Run(() => ExecuteRefreshCommandAsync(param)), CanExecuteRefreshCommand); _disableInspectionCommand = new DelegateCommand(ExecuteDisableInspectionCommand); - _quickFixCommand = new DelegateCommand(ExecuteQuickFixCommand); + _quickFixCommand = new DelegateCommand(ExecuteQuickFixCommand, CanExecuteQuickFixCommand); _quickFixInModuleCommand = new DelegateCommand(ExecuteQuickFixInModuleCommand); _quickFixInProjectCommand = new DelegateCommand(ExecuteQuickFixInProjectCommand); - _copyResultsCommand = new DelegateCommand(ExecuteCopyResultsCommand); + _copyResultsCommand = new DelegateCommand(ExecuteCopyResultsCommand, CanExecuteCopyResultsCommand); } private ObservableCollection _results; @@ -131,7 +131,7 @@ public IInspection SelectedInspection public bool CanRefresh { - get { return true /*_canRefresh*/; } + get { return _canRefresh; } private set { _canRefresh = value; @@ -153,13 +153,17 @@ private async void ExecuteRefreshCommandAsync(object parameter) return; } - CanRefresh = false; // if commands' CanExecute worked as expected, this junk wouldn't be needed IsBusy = true; _state.StateChanged += _state_StateChanged; _state.OnParseRequested(); } + private bool CanExecuteRefreshCommand(object parameter) + { + return !IsBusy; + } + private async void _state_StateChanged(object sender, ParserStateEventArgs e) { if (e.State != ParserState.Ready) @@ -197,6 +201,11 @@ private void ExecuteQuickFixCommand(object parameter) ExecuteQuickFixes(new[] {quickFix}); } + private bool CanExecuteQuickFixCommand(object parameter) + { + return !IsBusy && SelectedItem is IInspection; + } + private bool _canExecuteQuickFixInModule; public bool CanExecuteQuickFixInModule { @@ -287,5 +296,9 @@ private void ExecuteCopyResultsCommand(object parameter) _clipboard.Write(text); } + private bool CanExecuteCopyResultsCommand(object parameter) + { + return !IsBusy && _results != null && _results.Any(); + } } } diff --git a/RetailCoder.VBE/UI/Command/CommandBase.cs b/RetailCoder.VBE/UI/Command/CommandBase.cs index d36611402c..785e247ab1 100644 --- a/RetailCoder.VBE/UI/Command/CommandBase.cs +++ b/RetailCoder.VBE/UI/Command/CommandBase.cs @@ -14,14 +14,10 @@ public virtual bool CanExecute(object parameter) public abstract void Execute(object parameter); - public event EventHandler CanExecuteChanged; - protected void OnCanExecuteChanged() + public event EventHandler CanExecuteChanged { - var handler = CanExecuteChanged; - if (handler != null) - { - handler.Invoke(this, EventArgs.Empty); - } + add { CommandManager.RequerySuggested += value; } + remove { CommandManager.RequerySuggested -= value; } } } } \ No newline at end of file diff --git a/RetailCoder.VBE/UI/Command/DelegateCommand.cs b/RetailCoder.VBE/UI/Command/DelegateCommand.cs index 41311ae99a..44ff57293a 100644 --- a/RetailCoder.VBE/UI/Command/DelegateCommand.cs +++ b/RetailCoder.VBE/UI/Command/DelegateCommand.cs @@ -15,18 +15,9 @@ public DelegateCommand(Action execute, Predicate canExecute = nu _execute = execute; } - private bool _canExecuteState; public override bool CanExecute(object parameter) { - var previousState = _canExecuteState; - _canExecuteState = _canExecute == null || _canExecute.Invoke(parameter); - - if (previousState != _canExecuteState) - { - OnCanExecuteChanged(); - } - - return _canExecuteState; + return _canExecute == null || _canExecute.Invoke(parameter); } public override void Execute(object parameter) From f796e43f6eef397f9d4adeff6c45285d1f557eb3 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 00:15:25 -0500 Subject: [PATCH 10/18] fixed bug with continued lines in StripLineNumbers --- Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs b/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs index 636e3e4604..4880eed082 100644 --- a/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs +++ b/Rubberduck.VBEEditor/Extensions/CodeModuleExtensions.cs @@ -27,12 +27,12 @@ public static string[] GetSanitizedCode(this CodeModule module) private static void StripLineNumbers(string[] lines) { - var result = new string[lines.Length]; + var continuing = false; for(var line = 0; line < lines.Length; line++) { var code = lines[line]; int? lineNumber; - if (HasNumberedLine(code, out lineNumber)) + if (!continuing && HasNumberedLine(code, out lineNumber)) { var lineNumberLength = lineNumber.ToString().Length; if (lines[line].Length > lineNumberLength) @@ -41,6 +41,8 @@ private static void StripLineNumbers(string[] lines) lines[line] = new string(' ', lineNumberLength) + code.Substring(lineNumber.ToString().Length + 1); } } + + continuing = code.EndsWith("_"); } } From 421447cf7bf0a97499f65008629aee71bd5fa659 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 01:06:08 -0500 Subject: [PATCH 11/18] fixed bug where renamed declaration remained in parser state --- .../Inspections/DefaultProjectNameInspectionResult.cs | 10 +++++----- .../Inspections/UseMeaningfulNameInspectionResult.cs | 10 +++++----- .../Refactorings/Rename/RenamePresenterFactory.cs | 3 +-- .../Refactorings/Rename/RenameRefactoring.cs | 6 +++++- .../UI/CodeInspections/InspectionResultsViewModel.cs | 2 +- .../UI/Command/Refactorings/RefactorRenameCommand.cs | 2 +- Rubberduck.Parsing/VBA/RubberduckParserState.cs | 5 ++--- .../RubberduckCodePane/CodePaneWrapper.cs | 6 +++--- 8 files changed, 23 insertions(+), 21 deletions(-) diff --git a/RetailCoder.VBE/Inspections/DefaultProjectNameInspectionResult.cs b/RetailCoder.VBE/Inspections/DefaultProjectNameInspectionResult.cs index ec9b7ea784..9ffd2da8cc 100644 --- a/RetailCoder.VBE/Inspections/DefaultProjectNameInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/DefaultProjectNameInspectionResult.cs @@ -32,14 +32,14 @@ public DefaultProjectNameInspectionResult(IInspection inspection, Declaration ta public class RenameProjectQuickFix : CodeInspectionQuickFix { private readonly Declaration _target; - private readonly RubberduckParserState _parseResult; + private readonly RubberduckParserState _state; private readonly ICodePaneWrapperFactory _wrapperFactory; - public RenameProjectQuickFix(ParserRuleContext context, QualifiedSelection selection, Declaration target, RubberduckParserState parseResult, ICodePaneWrapperFactory wrapperFactory) + public RenameProjectQuickFix(ParserRuleContext context, QualifiedSelection selection, Declaration target, RubberduckParserState state, ICodePaneWrapperFactory wrapperFactory) : base(context, selection, string.Format(RubberduckUI.Rename_DeclarationType, RubberduckUI.ResourceManager.GetString("DeclarationType_" + DeclarationType.Project, RubberduckUI.Culture))) { _target = target; - _parseResult = parseResult; + _state = state; _wrapperFactory = wrapperFactory; } @@ -49,8 +49,8 @@ public override void Fix() using (var view = new RenameDialog()) { - var factory = new RenamePresenterFactory(vbe, view, _parseResult, new MessageBox(), _wrapperFactory); - var refactoring = new RenameRefactoring(factory, new ActiveCodePaneEditor(vbe, _wrapperFactory), new MessageBox()); + var factory = new RenamePresenterFactory(vbe, view, _state, new MessageBox(), _wrapperFactory); + var refactoring = new RenameRefactoring(factory, new ActiveCodePaneEditor(vbe, _wrapperFactory), new MessageBox(), _state); refactoring.Refactor(_target); } } diff --git a/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs b/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs index a687b6af79..742ddbf007 100644 --- a/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs @@ -32,15 +32,15 @@ public UseMeaningfulNameInspectionResult(IInspection inspection, Declaration tar public class RenameDeclarationQuickFix : CodeInspectionQuickFix { private readonly Declaration _target; - private readonly RubberduckParserState _parserState; + private readonly RubberduckParserState _state; private readonly ICodePaneWrapperFactory _wrapperFactory; private readonly IMessageBox _messageBox; - public RenameDeclarationQuickFix(ParserRuleContext context, QualifiedSelection selection, Declaration target, RubberduckParserState parserState, ICodePaneWrapperFactory wrapperFactory, IMessageBox messageBox) + public RenameDeclarationQuickFix(ParserRuleContext context, QualifiedSelection selection, Declaration target, RubberduckParserState state, ICodePaneWrapperFactory wrapperFactory, IMessageBox messageBox) : base(context, selection, string.Format(RubberduckUI.Rename_DeclarationType, RubberduckUI.ResourceManager.GetString("DeclarationType_" + target.DeclarationType, RubberduckUI.Culture))) { _target = target; - _parserState = parserState; + _state = state; _wrapperFactory = wrapperFactory; _messageBox = messageBox; } @@ -51,8 +51,8 @@ public override void Fix() using (var view = new RenameDialog()) { - var factory = new RenamePresenterFactory(vbe, view, _parserState, _messageBox, _wrapperFactory); - var refactoring = new RenameRefactoring(factory, new ActiveCodePaneEditor(vbe, _wrapperFactory), _messageBox); + var factory = new RenamePresenterFactory(vbe, view, _state, _messageBox, _wrapperFactory); + var refactoring = new RenameRefactoring(factory, new ActiveCodePaneEditor(vbe, _wrapperFactory), _messageBox, _state); refactoring.Refactor(_target); } } diff --git a/RetailCoder.VBE/Refactorings/Rename/RenamePresenterFactory.cs b/RetailCoder.VBE/Refactorings/Rename/RenamePresenterFactory.cs index 67575469f0..e823f28013 100644 --- a/RetailCoder.VBE/Refactorings/Rename/RenamePresenterFactory.cs +++ b/RetailCoder.VBE/Refactorings/Rename/RenamePresenterFactory.cs @@ -26,8 +26,7 @@ public RenamePresenterFactory(VBE vbe, IRenameView view, RubberduckParserState p public RenamePresenter Create() { var codePane = _wrapperFactory.Create(_vbe.ActiveCodePane); - var selection = new QualifiedSelection(new QualifiedModuleName(codePane.CodeModule.Parent), - codePane.Selection); + var selection = _vbe.ActiveCodePane == null ? new QualifiedSelection() : new QualifiedSelection(new QualifiedModuleName(codePane.CodeModule.Parent), codePane.Selection); return new RenamePresenter(_view, new RenameModel(_vbe, _parseResult, selection, _messageBox)); } } diff --git a/RetailCoder.VBE/Refactorings/Rename/RenameRefactoring.cs b/RetailCoder.VBE/Refactorings/Rename/RenameRefactoring.cs index ee041a3302..145691095c 100644 --- a/RetailCoder.VBE/Refactorings/Rename/RenameRefactoring.cs +++ b/RetailCoder.VBE/Refactorings/Rename/RenameRefactoring.cs @@ -9,6 +9,7 @@ using Rubberduck.Parsing; using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; using Rubberduck.UI; using Rubberduck.VBEditor; @@ -19,13 +20,15 @@ public class RenameRefactoring : IRefactoring private readonly IRefactoringPresenterFactory _factory; private readonly IActiveCodePaneEditor _editor; private readonly IMessageBox _messageBox; + private readonly RubberduckParserState _state; private RenameModel _model; - public RenameRefactoring(IRefactoringPresenterFactory factory, IActiveCodePaneEditor editor, IMessageBox messageBox) + public RenameRefactoring(IRefactoringPresenterFactory factory, IActiveCodePaneEditor editor, IMessageBox messageBox, RubberduckParserState state) { _factory = factory; _editor = editor; _messageBox = messageBox; + _state = state; } public void Refactor() @@ -212,6 +215,7 @@ private void RenameProject() if (project != null) { project.Name = _model.NewName; + _state.RemoveDeclaration(_model.Target); } } catch (COMException) diff --git a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs index 83e15e7e9c..65cc533157 100644 --- a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs +++ b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs @@ -203,7 +203,7 @@ private void ExecuteQuickFixCommand(object parameter) private bool CanExecuteQuickFixCommand(object parameter) { - return !IsBusy && SelectedItem is IInspection; + return true; //!IsBusy && SelectedItem is IInspection; } private bool _canExecuteQuickFixInModule; diff --git a/RetailCoder.VBE/UI/Command/Refactorings/RefactorRenameCommand.cs b/RetailCoder.VBE/UI/Command/Refactorings/RefactorRenameCommand.cs index 069f975ee2..5c1a11cf96 100644 --- a/RetailCoder.VBE/UI/Command/Refactorings/RefactorRenameCommand.cs +++ b/RetailCoder.VBE/UI/Command/Refactorings/RefactorRenameCommand.cs @@ -32,7 +32,7 @@ public override void Execute(object parameter) using (var view = new RenameDialog()) { var factory = new RenamePresenterFactory(Vbe, view, _state, new MessageBox(), _wrapperWrapperFactory); - var refactoring = new RenameRefactoring(factory, Editor, new MessageBox()); + var refactoring = new RenameRefactoring(factory, Editor, new MessageBox(), _state); var target = parameter as Declaration; if (target == null) diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs index f4707991a9..b8fb4c4488 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs @@ -227,8 +227,7 @@ public void ClearDeclarations(VBComponent component) foreach (var declaration in declarations) { - ResolutionState state; - _declarations.TryRemove(declaration, out state); + RemoveDeclaration(declaration); } } @@ -254,7 +253,7 @@ public TokenStreamRewriter GetRewriter(VBComponent component) /// /// /// Returns true when successful. - private bool RemoveDeclaration(Declaration declaration) + public bool RemoveDeclaration(Declaration declaration) { ResolutionState state; return _declarations.TryRemove(declaration, out state); diff --git a/Rubberduck.VBEEditor/VBEInterfaces/RubberduckCodePane/CodePaneWrapper.cs b/Rubberduck.VBEEditor/VBEInterfaces/RubberduckCodePane/CodePaneWrapper.cs index 680a0d3379..7d8f491c93 100644 --- a/Rubberduck.VBEEditor/VBEInterfaces/RubberduckCodePane/CodePaneWrapper.cs +++ b/Rubberduck.VBEEditor/VBEInterfaces/RubberduckCodePane/CodePaneWrapper.cs @@ -17,9 +17,9 @@ public int TopLine { get { return _codePane.TopLine; } set { _codePane.TopLine = value; } } - public int CountOfVisibleLines { get { return _codePane.CountOfVisibleLines; } } - public CodeModule CodeModule { get { return _codePane.CodeModule; } } - public vbext_CodePaneview CodePaneView { get { return _codePane.CodePaneView; } } + public int CountOfVisibleLines { get { return _codePane == null ? 0 : _codePane.CountOfVisibleLines; } } + public CodeModule CodeModule { get { return _codePane == null ? null : _codePane.CodeModule; } } + public vbext_CodePaneview CodePaneView { get { return _codePane == null ? vbext_CodePaneview.vbext_cv_FullModuleView : _codePane.CodePaneView; } } public CodePaneWrapper(CodePane codePane) { From 838bcc4a01102f9165cb992e5e5c71d57e37b3d8 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 01:50:31 -0500 Subject: [PATCH 12/18] added MultipleNamespaceDeclarationInspection --- .../AssignedByValParameterInspection.cs | 2 +- .../Inspections/InspectionsUI.Designer.cs | 27 ++++++++++++ .../Inspections/InspectionsUI.resx | 9 ++++ .../MultipleNamespaceDeclarationInspection.cs | 43 +++++++++++++++++++ RetailCoder.VBE/Rubberduck.csproj | 1 + .../CodeExplorerComponentViewModel.cs | 5 ++- .../CodeExplorerProjectViewModel.cs | 3 +- .../UI/CodeExplorer/CodeExplorerViewModel.cs | 2 +- 8 files changed, 87 insertions(+), 5 deletions(-) create mode 100644 RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs diff --git a/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs b/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs index 05491a7002..e60544a03f 100644 --- a/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs +++ b/RetailCoder.VBE/Inspections/AssignedByValParameterInspection.cs @@ -15,7 +15,7 @@ public AssignedByValParameterInspection(RubberduckParserState state) Severity = CodeInspectionSeverity.Warning; } - public override string Description { get { return RubberduckUI.ByValParameterIsAssigned_; } } + public override string Description { get { return InspectionsUI.AssignedByValParameterInspectionName; } } public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } } public override IEnumerable GetInspectionResults() diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs index f87dd36000..17eca8121b 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs +++ b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs @@ -303,6 +303,33 @@ internal static string MultipleDeclarationsInspectionName { } } + /// + /// Looks up a localized string similar to '{0}' has more than one namespace declaration.. + /// + internal static string MultipleNamespaceDeclarationInspection { + get { + return ResourceManager.GetString("MultipleNamespaceDeclarationInspection", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Rubberduck only uses the first '@Namespace' annotation in a code module; consider removing extraneous ones.. + /// + internal static string MultipleNamespaceDeclarationInspectionMeta { + get { + return ResourceManager.GetString("MultipleNamespaceDeclarationInspectionMeta", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Component has more than one namespace annotation.. + /// + internal static string MultipleNamespaceDeclarationInspectionName { + get { + return ResourceManager.GetString("MultipleNamespaceDeclarationInspectionName", resourceCulture); + } + } + /// /// Looks up a localized string similar to This is likely a bug. The return value of a function or property getter must be assigned before exiting, otherwise the program will not be working with expected results. If a function has no meaningful return value, consider declaring it as a 'Sub' procedure instead.. /// diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.resx b/RetailCoder.VBE/Inspections/InspectionsUI.resx index 1b0d6a3094..084b073b7c 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.resx +++ b/RetailCoder.VBE/Inspections/InspectionsUI.resx @@ -198,6 +198,15 @@ Instruction contains multiple declarations + + '{0}' has more than one namespace declaration. + + + Rubberduck only uses the first '@Namespace' annotation in a code module; consider removing extraneous ones. + + + Component has more than one namespace annotation. + This is likely a bug. The return value of a function or property getter must be assigned before exiting, otherwise the program will not be working with expected results. If a function has no meaningful return value, consider declaring it as a 'Sub' procedure instead. diff --git a/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs b/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs new file mode 100644 index 0000000000..86550adbf0 --- /dev/null +++ b/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs @@ -0,0 +1,43 @@ +using System.Collections.Generic; +using System.Linq; +using Antlr4.Runtime; +using Rubberduck.Parsing.Nodes; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; +using Rubberduck.UI; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections +{ + public sealed class MultipleNamespaceDeclarationInspection : InspectionBase + { + public MultipleNamespaceDeclarationInspection(RubberduckParserState state) + : base(state) + { + Severity = CodeInspectionSeverity.Warning; + } + + public override string Description { get { return InspectionsUI.MultipleNamespaceDeclarationInspection; } } + public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } + + public override IEnumerable GetInspectionResults() + { + var issues = UserDeclarations.Where(declaration => + (declaration.DeclarationType == DeclarationType.Class + || declaration.DeclarationType == DeclarationType.Module) + && declaration.Annotations.Split('\n').Count(annotation => + annotation.StartsWith(Parsing.Grammar.Annotations.AnnotationMarker + + Parsing.Grammar.Annotations.Namespace)) > 1); + return issues.Select(issue => + new MultipleNamespaceDeclarationInspectionResult(this, string.Format(Description, issue.ComponentName), issue)); + } + } + + public class MultipleNamespaceDeclarationInspectionResult : CodeInspectionResultBase + { + public MultipleNamespaceDeclarationInspectionResult(IInspection inspection, string result, Declaration target) + : base(inspection, result, target) + { + } + } +} \ No newline at end of file diff --git a/RetailCoder.VBE/Rubberduck.csproj b/RetailCoder.VBE/Rubberduck.csproj index 04fbb8a116..f55d11fe4e 100644 --- a/RetailCoder.VBE/Rubberduck.csproj +++ b/RetailCoder.VBE/Rubberduck.csproj @@ -302,6 +302,7 @@ True InspectionsUI.resx + diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs index 0803e04ea2..6cce8b5c47 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs @@ -32,11 +32,12 @@ public CodeExplorerComponentViewModel(Declaration declaration, IEnumerable item.Scope) .SelectMany(grouping => grouping.Where(item => MemberTypes.Contains(item.DeclarationType)) - .Select(item => new CodeExplorerMemberViewModel(item))); + .Select(item => new CodeExplorerMemberViewModel(item))) + .ToList(); var ns = _declaration.Annotations .Split('\n') - .FirstOrDefault(annotation => annotation.StartsWith(Parsing.Grammar.Annotations.Namespace)); + .FirstOrDefault(annotation => annotation.StartsWith(Parsing.Grammar.Annotations.AnnotationMarker + Parsing.Grammar.Annotations.Namespace)); if (ns != null) { diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs index 9bbc1a90cc..375e2f0301 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -24,7 +24,8 @@ public CodeExplorerProjectViewModel(Declaration declaration, IEnumerable item.ComponentName) .SelectMany(grouping => grouping.Where(item => ComponentTypes.Contains(item.DeclarationType)) - .Select(item => new CodeExplorerComponentViewModel(item, grouping))); + .Select(item => new CodeExplorerComponentViewModel(item, grouping))) + .ToList(); } public bool IsProtected { get { return _declaration.Project.Protection == vbext_ProjectProtection.vbext_pp_locked; } } diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs index a03ac7e3e6..6146bd3f3f 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs @@ -67,7 +67,7 @@ public IEnumerable Projects _projects = value; OnPropertyChanged(); } - } + } private void ParserState_StateChanged(object sender, ParserStateEventArgs e) { From 266e359eacf5a27641b5b2f8b10a6f800850e58e Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 02:04:21 -0500 Subject: [PATCH 13/18] moved InspectionBase to its own file, added CanIgnoreOnce virtual property getter --- RetailCoder.VBE/Inspections/IInspection.cs | 32 ---------------- RetailCoder.VBE/Inspections/InspectionBase.cs | 38 +++++++++++++++++++ .../MultipleNamespaceDeclarationInspection.cs | 2 + RetailCoder.VBE/Rubberduck.csproj | 1 + 4 files changed, 41 insertions(+), 32 deletions(-) create mode 100644 RetailCoder.VBE/Inspections/InspectionBase.cs diff --git a/RetailCoder.VBE/Inspections/IInspection.cs b/RetailCoder.VBE/Inspections/IInspection.cs index 2ee55c372e..0eceed32ab 100644 --- a/RetailCoder.VBE/Inspections/IInspection.cs +++ b/RetailCoder.VBE/Inspections/IInspection.cs @@ -1,7 +1,4 @@ using System.Collections.Generic; -using System.Linq; -using Rubberduck.Parsing.Symbols; -using Rubberduck.Parsing.VBA; namespace Rubberduck.Inspections { @@ -22,33 +19,4 @@ public interface IInspection : IInspectionModel string Meta { get; } } - - public abstract class InspectionBase : IInspection - { - protected readonly RubberduckParserState State; - protected InspectionBase(RubberduckParserState state) - { - State = state; - } - - public abstract string Description { get; } - public abstract CodeInspectionType InspectionType { get; } - public abstract IEnumerable GetInspectionResults(); - - public virtual string Name { get { return GetType().Name; } } - public virtual CodeInspectionSeverity Severity { get; set; } - public virtual string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } - public virtual string InspectionTypeName { get { return InspectionsUI.ResourceManager.GetString(InspectionType.ToString()); } } - protected virtual string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - protected virtual IEnumerable Declarations - { - get { return State.AllDeclarations.Where(declaration => !declaration.IsInspectionDisabled(AnnotationName)); } - } - - protected virtual IEnumerable UserDeclarations - { - get { return State.AllUserDeclarations.Where(declaration => !declaration.IsInspectionDisabled(AnnotationName)); } - } - } } diff --git a/RetailCoder.VBE/Inspections/InspectionBase.cs b/RetailCoder.VBE/Inspections/InspectionBase.cs new file mode 100644 index 0000000000..3127ecbfda --- /dev/null +++ b/RetailCoder.VBE/Inspections/InspectionBase.cs @@ -0,0 +1,38 @@ +using System.Collections.Generic; +using System.Linq; +using Rubberduck.Parsing.Symbols; +using Rubberduck.Parsing.VBA; + +namespace Rubberduck.Inspections +{ + public abstract class InspectionBase : IInspection + { + protected readonly RubberduckParserState State; + protected InspectionBase(RubberduckParserState state) + { + State = state; + } + + public abstract string Description { get; } + public abstract CodeInspectionType InspectionType { get; } + public abstract IEnumerable GetInspectionResults(); + + public virtual string Name { get { return GetType().Name; } } + public virtual CodeInspectionSeverity Severity { get; set; } + public virtual string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } + public virtual string InspectionTypeName { get { return InspectionsUI.ResourceManager.GetString(InspectionType.ToString()); } } + protected virtual string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } + + public virtual bool CanIgnoreOnce { get { return true; } } + + protected virtual IEnumerable Declarations + { + get { return State.AllDeclarations.Where(declaration => !declaration.IsInspectionDisabled(AnnotationName)); } + } + + protected virtual IEnumerable UserDeclarations + { + get { return State.AllUserDeclarations.Where(declaration => !declaration.IsInspectionDisabled(AnnotationName)); } + } + } +} \ No newline at end of file diff --git a/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs b/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs index 86550adbf0..8e2169e01d 100644 --- a/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs +++ b/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs @@ -20,6 +20,8 @@ public MultipleNamespaceDeclarationInspection(RubberduckParserState state) public override string Description { get { return InspectionsUI.MultipleNamespaceDeclarationInspection; } } public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } + public override bool CanIgnoreOnce { get { return false; } } + public override IEnumerable GetInspectionResults() { var issues = UserDeclarations.Where(declaration => diff --git a/RetailCoder.VBE/Rubberduck.csproj b/RetailCoder.VBE/Rubberduck.csproj index f55d11fe4e..c5784a3c4c 100644 --- a/RetailCoder.VBE/Rubberduck.csproj +++ b/RetailCoder.VBE/Rubberduck.csproj @@ -297,6 +297,7 @@ + True True From 4b1b4313b1f5fd8f3a70f96b8431da94bdb226dc Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 13:21:17 -0500 Subject: [PATCH 14/18] implemented IgnoreOnce quickfix, added to all inspections that should support it; required adding annotations to IdentifierReference and accounting for annotations in IdentifierReferenceResolver. --- .../Inspections/IInspectionModel.cs | 2 + .../IdentifierNotAssignedInspectionResult.cs | 3 +- .../IdentifierNotUsedInspectionResult.cs | 3 +- .../Inspections/IgnoreOnceQuickFix.cs | 43 +++++++++++++++++++ .../ImplicitActiveSheetReferenceInspection.cs | 9 ++-- .../ImplicitByRefParameterInspectionResult.cs | 3 +- .../ImplicitPublicMemberInspectionResult.cs | 3 +- ...plicitVariantReturnTypeInspectionResult.cs | 3 +- RetailCoder.VBE/Inspections/InspectionBase.cs | 4 +- .../Inspections/InspectionsUI.Designer.cs | 9 ++++ .../Inspections/InspectionsUI.resx | 3 ++ .../MultipleDeclarationsInspectionResult.cs | 3 +- .../MultipleNamespaceDeclarationInspection.cs | 6 --- .../NonReturningFunctionInspectionResult.cs | 3 +- ...oleteCallStatementUsageInspectionResult.cs | 3 +- .../ObsoleteCommentSyntaxInspectionResult.cs | 1 + .../ObsoleteGlobalInspectionResult.cs | 5 ++- ...soleteLetStatementUsageInspectionResult.cs | 3 +- .../ObsoleteTypeHintInspectionResult.cs | 3 +- .../Inspections/OptionBaseInspection.cs | 4 -- .../ParameterNotUsedInspectionResult.cs | 3 +- .../UnassignedVariableUsageInspection.cs | 5 ++- ...UnassignedVariableUsageInspectionResult.cs | 5 ++- .../UntypedFunctionUsageInspectionResult.cs | 3 +- .../UseMeaningfulNameInspectionResult.cs | 3 +- ...VariableTypeNotDeclaredInspectionResult.cs | 3 +- RetailCoder.VBE/Rubberduck.csproj | 1 + .../Settings/CodeInspectionSettings.cs | 3 ++ .../Symbols/DeclarationSymbolsListener.cs | 13 ++---- .../Symbols/IdentifierReference.cs | 12 +++++- .../Symbols/IdentifierReferenceResolver.cs | 23 +++++++++- Rubberduck.Parsing/VBA/RubberduckParser.cs | 2 +- 32 files changed, 142 insertions(+), 50 deletions(-) create mode 100644 RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs diff --git a/RetailCoder.VBE/Inspections/IInspectionModel.cs b/RetailCoder.VBE/Inspections/IInspectionModel.cs index b2e364fb15..a07cfaf4e6 100644 --- a/RetailCoder.VBE/Inspections/IInspectionModel.cs +++ b/RetailCoder.VBE/Inspections/IInspectionModel.cs @@ -10,6 +10,8 @@ public interface IInspectionModel /// string Name { get; } + string AnnotationName { get; } + /// /// Gets a short description for the code inspection. /// diff --git a/RetailCoder.VBE/Inspections/IdentifierNotAssignedInspectionResult.cs b/RetailCoder.VBE/Inspections/IdentifierNotAssignedInspectionResult.cs index e08ccedff7..01ced0e460 100644 --- a/RetailCoder.VBE/Inspections/IdentifierNotAssignedInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/IdentifierNotAssignedInspectionResult.cs @@ -15,9 +15,10 @@ public IdentifierNotAssignedInspectionResult(IInspection inspection, Declaration ParserRuleContext context, QualifiedModuleName qualifiedName) : base(inspection, target, context, qualifiedName) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new RemoveUnassignedIdentifierQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/IdentifierNotUsedInspectionResult.cs b/RetailCoder.VBE/Inspections/IdentifierNotUsedInspectionResult.cs index 10d0ecc573..4585382a10 100644 --- a/RetailCoder.VBE/Inspections/IdentifierNotUsedInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/IdentifierNotUsedInspectionResult.cs @@ -15,9 +15,10 @@ public IdentifierNotUsedInspectionResult(IInspection inspection, Declaration tar ParserRuleContext context, QualifiedModuleName qualifiedName) : base(inspection, string.Format(inspection.Description, target.IdentifierName), qualifiedName, context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new RemoveUnusedDeclarationQuickFix(context, QualifiedSelection), + new IgnoreOnceQuickFix(context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs b/RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs new file mode 100644 index 0000000000..e2daceca4e --- /dev/null +++ b/RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs @@ -0,0 +1,43 @@ +using Antlr4.Runtime; +using Rubberduck.Parsing.VBA; +using Rubberduck.VBEditor; + +namespace Rubberduck.Inspections +{ + public class IgnoreOnceQuickFix : CodeInspectionQuickFix + { + private readonly string _annotationText; + private readonly string _inspectionName; + + public IgnoreOnceQuickFix(ParserRuleContext context, QualifiedSelection selection, string inspectionName) + : base(context, selection, InspectionsUI.IgnoreOnce) + { + _inspectionName = inspectionName; + _annotationText = "'" + Parsing.Grammar.Annotations.AnnotationMarker + + Parsing.Grammar.Annotations.IgnoreInspection + ' ' + inspectionName; + } + + public override bool CanFixInModule { get { return false; } } // not quite "once" if applied to entire module + public override bool CanFixInProject { get { return false; } } // use "disable this inspection" instead of ignoring across the project + + public override void Fix() + { + var codeModule = Selection.QualifiedName.Component.CodeModule; + var insertLine = Selection.Selection.StartLine; + var codeLine = codeModule.get_Lines(insertLine - 1, 1); + var annotationText = _annotationText; + var ignoreAnnotation = "'" + Parsing.Grammar.Annotations.AnnotationMarker + Parsing.Grammar.Annotations.IgnoreInspection; + + int commentStart; + if (codeLine.HasComment(out commentStart) && codeLine.Substring(commentStart).StartsWith(ignoreAnnotation)) + { + annotationText = codeLine + ' ' + _inspectionName; + codeModule.ReplaceLine(insertLine - 1, annotationText); + } + else + { + codeModule.InsertLines(insertLine, annotationText); + } + } + } +} \ No newline at end of file diff --git a/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs b/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs index 96e68e42d1..632fb6569f 100644 --- a/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs +++ b/RetailCoder.VBE/Inspections/ImplicitActiveSheetReferenceInspection.cs @@ -51,14 +51,17 @@ public override IEnumerable GetInspectionResults() public class ImplicitActiveSheetReferenceInspectionResult : CodeInspectionResultBase { - //private readonly IEnumerable _quickFixes; + private readonly IEnumerable _quickFixes; public ImplicitActiveSheetReferenceInspectionResult(IInspection inspection, string result, ParserRuleContext context, QualifiedModuleName qualifiedName) : base(inspection, result, qualifiedName, context) { - //_quickFixes = new CodeInspectionQuickFix[]{}; + _quickFixes = new CodeInspectionQuickFix[] + { + new IgnoreOnceQuickFix(context, QualifiedSelection, Inspection.AnnotationName), + }; } - //public override IEnumerable QuickFixes { get { return _quickFixes; } } + public override IEnumerable QuickFixes { get { return _quickFixes; } } } } diff --git a/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspectionResult.cs b/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspectionResult.cs index 68db2d0469..1458dc7397 100644 --- a/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ImplicitByRefParameterInspectionResult.cs @@ -15,9 +15,10 @@ public class ImplicitByRefParameterInspectionResult : CodeInspectionResultBase public ImplicitByRefParameterInspectionResult(IInspection inspection, string result, QualifiedContext qualifiedContext) : base(inspection, result, qualifiedContext.ModuleName, qualifiedContext.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new ImplicitByRefParameterQuickFix(Context, QualifiedSelection, RubberduckUI.Inspections_PassParamByRefExplicitly, Tokens.ByRef), + new IgnoreOnceQuickFix(qualifiedContext.Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspectionResult.cs b/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspectionResult.cs index 2c40b68937..c5b85f36d8 100644 --- a/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ImplicitPublicMemberInspectionResult.cs @@ -15,9 +15,10 @@ public class ImplicitPublicMemberInspectionResult : CodeInspectionResultBase public ImplicitPublicMemberInspectionResult(IInspection inspection, string result, QualifiedContext qualifiedContext) : base(inspection, result, qualifiedContext.ModuleName, qualifiedContext.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new SpecifyExplicitPublicModifierQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(qualifiedContext.Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspectionResult.cs b/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspectionResult.cs index 1eabc68b79..76f8dae6d8 100644 --- a/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ImplicitVariantReturnTypeInspectionResult.cs @@ -17,9 +17,10 @@ public class ImplicitVariantReturnTypeInspectionResult : CodeInspectionResultBas public ImplicitVariantReturnTypeInspectionResult(IInspection inspection, string name, QualifiedContext qualifiedContext) : base(inspection, name, qualifiedContext.ModuleName, qualifiedContext.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new SetExplicitVariantReturnTypeQuickFix(Context, QualifiedSelection, RubberduckUI.Inspections_ReturnExplicitVariant), + new IgnoreOnceQuickFix(qualifiedContext.Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/InspectionBase.cs b/RetailCoder.VBE/Inspections/InspectionBase.cs index 3127ecbfda..685e0578a8 100644 --- a/RetailCoder.VBE/Inspections/InspectionBase.cs +++ b/RetailCoder.VBE/Inspections/InspectionBase.cs @@ -21,9 +21,7 @@ protected InspectionBase(RubberduckParserState state) public virtual CodeInspectionSeverity Severity { get; set; } public virtual string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } public virtual string InspectionTypeName { get { return InspectionsUI.ResourceManager.GetString(InspectionType.ToString()); } } - protected virtual string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } - - public virtual bool CanIgnoreOnce { get { return true; } } + public virtual string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } protected virtual IEnumerable Declarations { diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs index 17eca8121b..73e5301557 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs +++ b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs @@ -159,6 +159,15 @@ internal static string EmptyStringLiteralInspectionQuickFix { } } + /// + /// Looks up a localized string similar to Ignore once. + /// + internal static string IgnoreOnce { + get { + return ResourceManager.GetString("IgnoreOnce", resourceCulture); + } + } + /// /// Looks up a localized string similar to Implicit references to the active sheet make the code frail and harder to debug. Consider making these references explicit when they're intended, and prefer working off object references.. /// diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.resx b/RetailCoder.VBE/Inspections/InspectionsUI.resx index 084b073b7c..7816da9eab 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.resx +++ b/RetailCoder.VBE/Inspections/InspectionsUI.resx @@ -150,6 +150,9 @@ Replace empty string with the 'vbNullString' constant + + Ignore once + Implicit references to the active sheet make the code frail and harder to debug. Consider making these references explicit when they're intended, and prefer working off object references. diff --git a/RetailCoder.VBE/Inspections/MultipleDeclarationsInspectionResult.cs b/RetailCoder.VBE/Inspections/MultipleDeclarationsInspectionResult.cs index 8659ee5e0d..3cd2818c60 100644 --- a/RetailCoder.VBE/Inspections/MultipleDeclarationsInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/MultipleDeclarationsInspectionResult.cs @@ -16,9 +16,10 @@ public class MultipleDeclarationsInspectionResult : CodeInspectionResultBase public MultipleDeclarationsInspectionResult(IInspection inspection, string result, QualifiedContext qualifiedContext) : base(inspection, result, qualifiedContext.ModuleName, qualifiedContext.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new SplitMultipleDeclarationsQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(qualifiedContext.Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs b/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs index 8e2169e01d..a6b530b5c4 100644 --- a/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs +++ b/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs @@ -1,11 +1,7 @@ using System.Collections.Generic; using System.Linq; -using Antlr4.Runtime; -using Rubberduck.Parsing.Nodes; using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; -using Rubberduck.UI; -using Rubberduck.VBEditor; namespace Rubberduck.Inspections { @@ -20,8 +16,6 @@ public MultipleNamespaceDeclarationInspection(RubberduckParserState state) public override string Description { get { return InspectionsUI.MultipleNamespaceDeclarationInspection; } } public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } - public override bool CanIgnoreOnce { get { return false; } } - public override IEnumerable GetInspectionResults() { var issues = UserDeclarations.Where(declaration => diff --git a/RetailCoder.VBE/Inspections/NonReturningFunctionInspectionResult.cs b/RetailCoder.VBE/Inspections/NonReturningFunctionInspectionResult.cs index 05c16f9d89..af80cf8fcb 100644 --- a/RetailCoder.VBE/Inspections/NonReturningFunctionInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/NonReturningFunctionInspectionResult.cs @@ -18,9 +18,10 @@ public NonReturningFunctionInspectionResult(IInspection inspection, string resul { _quickFixes = isInterfaceImplementation ? new CodeInspectionQuickFix[] { } - : new[] + : new CodeInspectionQuickFix[] { new ConvertToProcedureQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/ObsoleteCallStatementUsageInspectionResult.cs b/RetailCoder.VBE/Inspections/ObsoleteCallStatementUsageInspectionResult.cs index 942919f776..afb26d534b 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteCallStatementUsageInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteCallStatementUsageInspectionResult.cs @@ -16,9 +16,10 @@ public class ObsoleteCallStatementUsageInspectionResult : CodeInspectionResultBa public ObsoleteCallStatementUsageInspectionResult(IInspection inspection, QualifiedContext qualifiedContext) : base(inspection, inspection.Description, qualifiedContext.ModuleName, qualifiedContext.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new RemoveExplicitCallStatemntQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspectionResult.cs b/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspectionResult.cs index b75ffb18f3..44a8fb78dd 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteCommentSyntaxInspectionResult.cs @@ -21,6 +21,7 @@ public ObsoleteCommentSyntaxInspectionResult(IInspection inspection, CommentNode { new ReplaceCommentMarkerQuickFix(Context, QualifiedSelection, comment), new RemoveCommentQuickFix(Context, QualifiedSelection, comment), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/ObsoleteGlobalInspectionResult.cs b/RetailCoder.VBE/Inspections/ObsoleteGlobalInspectionResult.cs index 357637fe5c..cd6bc11281 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteGlobalInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteGlobalInspectionResult.cs @@ -15,9 +15,10 @@ public class ObsoleteGlobalInspectionResult : CodeInspectionResultBase public ObsoleteGlobalInspectionResult(IInspection inspection, string result, QualifiedContext context) : base(inspection, result, context.ModuleName, context.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { - new ReplaceGlobalModifierQuickFix(Context, QualifiedSelection) + new ReplaceGlobalModifierQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/ObsoleteLetStatementUsageInspectionResult.cs b/RetailCoder.VBE/Inspections/ObsoleteLetStatementUsageInspectionResult.cs index 0fc69a0c2b..cbaca6b6e0 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteLetStatementUsageInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteLetStatementUsageInspectionResult.cs @@ -15,9 +15,10 @@ public class ObsoleteLetStatementUsageInspectionResult : CodeInspectionResultBas public ObsoleteLetStatementUsageInspectionResult(IInspection inspection, QualifiedContext qualifiedContext) : base(inspection, inspection.Description, qualifiedContext.ModuleName, qualifiedContext.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new RemoveExplicitLetStatementQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspectionResult.cs b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspectionResult.cs index 51af2af710..320ec47ba9 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspectionResult.cs @@ -18,9 +18,10 @@ public class ObsoleteTypeHintInspectionResult : CodeInspectionResultBase public ObsoleteTypeHintInspectionResult(IInspection inspection, string result, QualifiedContext qualifiedContext, Declaration declaration) : base(inspection, result, qualifiedContext.ModuleName, qualifiedContext.Context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new RemoveTypeHintsQuickFix(Context, QualifiedSelection, declaration), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/OptionBaseInspection.cs b/RetailCoder.VBE/Inspections/OptionBaseInspection.cs index f6e24c85cc..c28ec30642 100644 --- a/RetailCoder.VBE/Inspections/OptionBaseInspection.cs +++ b/RetailCoder.VBE/Inspections/OptionBaseInspection.cs @@ -4,18 +4,14 @@ using Rubberduck.Parsing.Symbols; using Rubberduck.Parsing.VBA; using Rubberduck.UI; -using Rubberduck.VBEditor.VBEInterfaces.RubberduckCodePane; namespace Rubberduck.Inspections { public sealed class OptionBaseInspection : InspectionBase { - private readonly ICodePaneWrapperFactory _wrapperFactory; - public OptionBaseInspection(RubberduckParserState state) : base(state) { - _wrapperFactory = new CodePaneWrapperFactory(); Severity = CodeInspectionSeverity.Warning; } diff --git a/RetailCoder.VBE/Inspections/ParameterNotUsedInspectionResult.cs b/RetailCoder.VBE/Inspections/ParameterNotUsedInspectionResult.cs index ce4e596073..c79089ce0f 100644 --- a/RetailCoder.VBE/Inspections/ParameterNotUsedInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ParameterNotUsedInspectionResult.cs @@ -16,9 +16,10 @@ public ParameterNotUsedInspectionResult(IInspection inspection, string result, RemoveParametersRefactoring refactoring, RubberduckParserState parseResult) : base(inspection, result, qualifiedName.QualifiedModuleName, context) { - _quickFixes = isInterfaceImplementation ? new CodeInspectionQuickFix[] {} : new[] + _quickFixes = isInterfaceImplementation ? new CodeInspectionQuickFix[] {} : new CodeInspectionQuickFix[] { new RemoveUnusedParameterQuickFix(Context, QualifiedSelection, refactoring, parseResult), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs b/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs index 39a10b5686..2a78abad26 100644 --- a/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs +++ b/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs @@ -22,11 +22,12 @@ public override IEnumerable GetInspectionResults() var usages = UserDeclarations.Where(declaration => declaration.DeclarationType == DeclarationType.Variable && !declaration.References.Any(reference => reference.IsAssignment)) - .SelectMany(declaration => declaration.References); + .SelectMany(declaration => declaration.References) + .Where(usage => !usage.IsInspectionDisabled(AnnotationName)); foreach (var issue in usages) { - yield return new UnassignedVariableUsageInspectionResult(this, string.Format(Name, issue.Context.GetText()), issue.Context, issue.QualifiedModuleName); + yield return new UnassignedVariableUsageInspectionResult(this, string.Format(Description, issue.Context.GetText()), issue.Context, issue.QualifiedModuleName); } } } diff --git a/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspectionResult.cs b/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspectionResult.cs index 50c88b55ac..8f6e65ed32 100644 --- a/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/UnassignedVariableUsageInspectionResult.cs @@ -14,9 +14,10 @@ public UnassignedVariableUsageInspectionResult(IInspection inspection, string re ParserRuleContext context, QualifiedModuleName qualifiedName) : base(inspection, result, qualifiedName, context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { - new RemoveUnassignedVariableUsageQuickFix(Context, QualifiedSelection) + new RemoveUnassignedVariableUsageQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs index 2d0c7b116c..07694de569 100644 --- a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs @@ -12,9 +12,10 @@ public class UntypedFunctionUsageInspectionResult : CodeInspectionResultBase public UntypedFunctionUsageInspectionResult(IInspection inspection, string result, QualifiedModuleName qualifiedName, ParserRuleContext context) : base(inspection, result, qualifiedName, context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new UntypedFunctionUsageQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs b/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs index 742ddbf007..e1c8989c91 100644 --- a/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/UseMeaningfulNameInspectionResult.cs @@ -17,9 +17,10 @@ public class UseMeaningfulNameInspectionResult : CodeInspectionResultBase public UseMeaningfulNameInspectionResult(IInspection inspection, Declaration target, RubberduckParserState parserState, ICodePaneWrapperFactory wrapperFactory, IMessageBox messageBox) : base(inspection, string.Format(inspection.Description, RubberduckUI.ResourceManager.GetString("DeclarationType_" + target.DeclarationType, RubberduckUI.Culture), target.IdentifierName), target) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new RenameDeclarationQuickFix(target.Context, target.QualifiedSelection, target, parserState, wrapperFactory, messageBox), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspectionResult.cs b/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspectionResult.cs index 7ffb7dab44..0c55448a46 100644 --- a/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/VariableTypeNotDeclaredInspectionResult.cs @@ -14,9 +14,10 @@ public class VariableTypeNotDeclaredInspectionResult : CodeInspectionResultBase public VariableTypeNotDeclaredInspectionResult(IInspection inspection, string result, ParserRuleContext context, QualifiedModuleName qualifiedName) : base(inspection, result, qualifiedName, context) { - _quickFixes = new[] + _quickFixes = new CodeInspectionQuickFix[] { new DeclareAsExplicitVariantQuickFix(Context, QualifiedSelection), + new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } diff --git a/RetailCoder.VBE/Rubberduck.csproj b/RetailCoder.VBE/Rubberduck.csproj index c5784a3c4c..570ab6199e 100644 --- a/RetailCoder.VBE/Rubberduck.csproj +++ b/RetailCoder.VBE/Rubberduck.csproj @@ -295,6 +295,7 @@ + diff --git a/RetailCoder.VBE/Settings/CodeInspectionSettings.cs b/RetailCoder.VBE/Settings/CodeInspectionSettings.cs index 67da0cabab..a3640afb98 100644 --- a/RetailCoder.VBE/Settings/CodeInspectionSettings.cs +++ b/RetailCoder.VBE/Settings/CodeInspectionSettings.cs @@ -31,6 +31,9 @@ public class CodeInspectionSetting : IInspectionModel [XmlIgnore] public string Description { get; set; } // not serialized because culture-dependent + [XmlIgnore] + public string AnnotationName { get; set; } + [XmlAttribute] public CodeInspectionSeverity Severity { get; set; } diff --git a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs index 4e579494cb..9ca77307b4 100644 --- a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs +++ b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs @@ -87,17 +87,10 @@ private string FindAnnotations(int line) return null; } - try + var commentAbove = _comments.SingleOrDefault(comment => comment.QualifiedSelection.Selection.EndLine == line - 1); + if (commentAbove != null && commentAbove.CommentText.StartsWith("@")) { - var commentAbove = _comments.SingleOrDefault(comment => comment.QualifiedSelection.Selection.EndLine == line - 1); - if (commentAbove != null && commentAbove.CommentText.StartsWith("@")) - { - return commentAbove.CommentText; - } - } - catch (InvalidOperationException) - { - throw; + return commentAbove.CommentText; } return null; } diff --git a/Rubberduck.Parsing/Symbols/IdentifierReference.cs b/Rubberduck.Parsing/Symbols/IdentifierReference.cs index 62c577c2ad..f0f0e6f344 100644 --- a/Rubberduck.Parsing/Symbols/IdentifierReference.cs +++ b/Rubberduck.Parsing/Symbols/IdentifierReference.cs @@ -7,7 +7,7 @@ namespace Rubberduck.Parsing.Symbols { public class IdentifierReference { - public IdentifierReference(QualifiedModuleName qualifiedName, string parentScope, string identifierName, Selection selection, ParserRuleContext context, Declaration declaration, bool isAssignmentTarget = false, bool hasExplicitLetStatement = false) + public IdentifierReference(QualifiedModuleName qualifiedName, string parentScope, string identifierName, Selection selection, ParserRuleContext context, Declaration declaration, bool isAssignmentTarget = false, bool hasExplicitLetStatement = false, string annotations = null) { _qualifiedName = qualifiedName; _parentScope = parentScope; @@ -17,6 +17,7 @@ public IdentifierReference(QualifiedModuleName qualifiedName, string parentScope _declaration = declaration; _hasExplicitLetStatement = hasExplicitLetStatement; _isAssignmentTarget = isAssignmentTarget; + _annotations = annotations ?? string.Empty; } private readonly QualifiedModuleName _qualifiedName; @@ -40,6 +41,15 @@ public IdentifierReference(QualifiedModuleName qualifiedName, string parentScope private readonly Declaration _declaration; public Declaration Declaration { get { return _declaration; } } + private readonly string _annotations; + public string Annotations { get { return _annotations ?? string.Empty; } } + + public bool IsInspectionDisabled(string inspectionName) + { + return Annotations.Contains(Grammar.Annotations.IgnoreInspection) + && Annotations.Contains(inspectionName); + } + private readonly bool _hasExplicitLetStatement; public bool HasExplicitLetStatement { get { return _hasExplicitLetStatement; } } diff --git a/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs b/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs index 7c7879c935..90f22721a9 100644 --- a/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs +++ b/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs @@ -3,6 +3,7 @@ using System.Linq; using Antlr4.Runtime; using Rubberduck.Parsing.Grammar; +using Rubberduck.Parsing.Nodes; using Rubberduck.VBEditor; namespace Rubberduck.Parsing.Symbols @@ -17,6 +18,7 @@ private enum ContextAccessorType } private readonly IEnumerable _declarations; + private readonly IEnumerable _comments; private readonly QualifiedModuleName _qualifiedModuleName; @@ -29,10 +31,11 @@ private enum ContextAccessorType private readonly Stack _withBlockQualifiers; private readonly HashSet _alreadyResolved; - public IdentifierReferenceResolver(QualifiedModuleName qualifiedModuleName, IEnumerable declarations) + public IdentifierReferenceResolver(QualifiedModuleName qualifiedModuleName, IEnumerable declarations, IEnumerable comments) { _qualifiedModuleName = qualifiedModuleName; _declarations = declarations; + _comments = comments; _withBlockQualifiers = new Stack(); _alreadyResolved = new HashSet(); @@ -146,7 +149,23 @@ private IdentifierReference CreateReference(ParserRuleContext callSiteContext, D } var name = callSiteContext.GetText(); var selection = callSiteContext.GetSelection(); - return new IdentifierReference(_qualifiedModuleName, _currentScope.Scope, name, selection, callSiteContext, callee, isAssignmentTarget, hasExplicitLetStatement); + var annotations = FindAnnotations(selection.StartLine); + return new IdentifierReference(_qualifiedModuleName, _currentScope.Scope, name, selection, callSiteContext, callee, isAssignmentTarget, hasExplicitLetStatement, annotations); + } + + private string FindAnnotations(int line) + { + if (_comments == null) + { + return null; + } + + var commentAbove = _comments.SingleOrDefault(comment => comment.QualifiedSelection.Selection.EndLine == line - 1); + if (commentAbove != null && commentAbove.CommentText.StartsWith("@")) + { + return commentAbove.CommentText; + } + return null; } private Declaration ResolveType(VBAParser.ComplexTypeContext context) diff --git a/Rubberduck.Parsing/VBA/RubberduckParser.cs b/Rubberduck.Parsing/VBA/RubberduckParser.cs index 414b75d764..faf08316b0 100644 --- a/Rubberduck.Parsing/VBA/RubberduckParser.cs +++ b/Rubberduck.Parsing/VBA/RubberduckParser.cs @@ -298,7 +298,7 @@ private void ResolveReferences(VBComponent component, IParseTree tree, Cancellat _state.SetModuleState(component, ParserState.Resolving); - var resolver = new IdentifierReferenceResolver(new QualifiedModuleName(component), _state.AllDeclarations); + var resolver = new IdentifierReferenceResolver(new QualifiedModuleName(component), _state.AllDeclarations, _state.AllComments); var listener = new IdentifierReferenceListener(resolver, token); var walker = new ParseTreeWalker(); try From ccfbf81bf884123b59d5eeab75c73d4c2a7222c3 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 14:37:52 -0500 Subject: [PATCH 15/18] fixed bug in ExecuteCopyResultsCommand implementation --- .../Inspections/CodeInspectionResultBase.cs | 12 ++++++++++++ RetailCoder.VBE/Inspections/ICodeInspectionResult.cs | 1 + .../UI/CodeInspections/InspectionResultsViewModel.cs | 4 ++-- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs b/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs index 436f34666f..e057057c5e 100644 --- a/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs +++ b/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs @@ -93,5 +93,17 @@ public override string ToString() module.ComponentName, QualifiedSelection.Selection.StartLine); } + + public string ToCsvString() + { + var module = QualifiedSelection.QualifiedName; + return string.Format( + "{0}, {1}, {2}, {3}, {4}", + Inspection.Severity, + Name, + module.ProjectName, + module.ComponentName, + QualifiedSelection.Selection.StartLine); + } } } diff --git a/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs b/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs index 19b42582b3..b49cacd9bf 100644 --- a/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs @@ -13,5 +13,6 @@ public interface ICodeInspectionResult string Name { get; } QualifiedSelection QualifiedSelection { get; } IInspection Inspection { get; } + string ToCsvString(); } } diff --git a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs index 65cc533157..3ffb24ef51 100644 --- a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs +++ b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsViewModel.cs @@ -287,11 +287,11 @@ private void ExecuteCopyResultsCommand(object parameter) return; } - var results = string.Join("\n", _results.Select(result => result.ToString()), "\n"); + var results = string.Join("\n", _results.Select(result => result.ToString() + Environment.NewLine).ToArray()); var resource = _results.Count == 1 ? RubberduckUI.CodeInspections_NumberOfIssuesFound_Singular : RubberduckUI.CodeInspections_NumberOfIssuesFound_Plural; - var text = string.Format(resource, DateTime.Now, _results.Count) + results; + var text = string.Format(resource, DateTime.Now, _results.Count) + Environment.NewLine + results; _clipboard.Write(text); } From ed7fd66cccc4dea752566e4c71a60d2a838cede8 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 16:27:05 -0500 Subject: [PATCH 16/18] implemented rough hierarchical templates for code explorer. --- .../Inspections/IgnoreOnceQuickFix.cs | 3 +- .../CodeExplorerComponentViewModel.cs | 7 +++- .../UI/CodeExplorer/CodeExplorerControl.xaml | 42 +++++++++++++++---- .../CodeExplorerMemberViewModel.cs | 17 +++++++- .../CodeExplorerProjectViewModel.cs | 12 +++++- .../UI/CodeExplorer/CodeExplorerViewModel.cs | 9 ++-- .../Symbols/DeclarationSymbolsListener.cs | 1 + .../Symbols/IdentifierReferenceResolver.cs | 2 +- 8 files changed, 75 insertions(+), 18 deletions(-) diff --git a/RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs b/RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs index e2daceca4e..063b15d5c6 100644 --- a/RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs +++ b/RetailCoder.VBE/Inspections/IgnoreOnceQuickFix.cs @@ -24,7 +24,8 @@ public override void Fix() { var codeModule = Selection.QualifiedName.Component.CodeModule; var insertLine = Selection.Selection.StartLine; - var codeLine = codeModule.get_Lines(insertLine - 1, 1); + + var codeLine = insertLine == 1 ? string.Empty : codeModule.get_Lines(insertLine - 1, 1); var annotationText = _annotationText; var ignoreAnnotation = "'" + Parsing.Grammar.Annotations.AnnotationMarker + Parsing.Grammar.Annotations.IgnoreInspection; diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs index 6cce8b5c47..63b2742356 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs @@ -31,8 +31,9 @@ public CodeExplorerComponentViewModel(Declaration declaration, IEnumerable item.Scope) .SelectMany(grouping => - grouping.Where(item => MemberTypes.Contains(item.DeclarationType)) - .Select(item => new CodeExplorerMemberViewModel(item))) + grouping.Where(item => item.ParentDeclaration.Equals(declaration) && MemberTypes.Contains(item.DeclarationType)) + .Select(item => new CodeExplorerMemberViewModel(item, grouping))) + .OrderBy(item => item.Name) .ToList(); var ns = _declaration.Annotations @@ -51,6 +52,8 @@ public CodeExplorerComponentViewModel(Declaration declaration, IEnumerable Members { get { return _members; } } + private bool _isErrorState; public bool IsErrorState { get { return _isErrorState; } set { _isErrorState = value; OnPropertyChanged(); } } diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml index d1ce00b2e2..fd07b0e4b2 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml @@ -77,16 +77,42 @@ - - - + + + + + + + + + + + + + + + + + + + + + @@ -123,12 +149,12 @@ - + MouseDoubleClick="TreeView_OnMouseDoubleClick" + ItemsSource="{Binding Projects}" + ItemTemplate="{StaticResource CodeExplorerTreeViewTemplate}"> diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs index de03924319..998f7123cf 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerMemberViewModel.cs @@ -1,3 +1,5 @@ +using System.Collections.Generic; +using System.Linq; using Rubberduck.Parsing.Symbols; namespace Rubberduck.UI.CodeExplorer @@ -6,13 +8,26 @@ public class CodeExplorerMemberViewModel : ViewModelBase { private readonly Declaration _declaration; - public CodeExplorerMemberViewModel(Declaration declaration) + private static readonly DeclarationType[] SubMemberTypes = + { + DeclarationType.EnumerationMember, + DeclarationType.UserDefinedTypeMember + }; + + public CodeExplorerMemberViewModel(Declaration declaration, IEnumerable declarations) { _declaration = declaration; + if (declarations != null) + { + _members = declarations.Where(item => SubMemberTypes.Contains(item.DeclarationType) && item.ParentDeclaration.Equals(declaration)) + .Select(item => new CodeExplorerMemberViewModel(item, null)); + } } public string Name { get { return _declaration.IdentifierName; } } //public string Signature { get { return _declaration.IdentifierName; } } + private readonly IEnumerable _members; + public IEnumerable Members { get { return _members; } } } } \ No newline at end of file diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs index 375e2f0301..9a67937512 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -1,7 +1,10 @@ using System.Collections.Generic; +using System.Drawing; using System.Linq; +using System.Windows.Media.Imaging; using Microsoft.Vbe.Interop; using Rubberduck.Parsing.Symbols; +using resx = Rubberduck.Properties.Resources; namespace Rubberduck.UI.CodeExplorer { @@ -9,6 +12,7 @@ public class CodeExplorerProjectViewModel : ViewModelBase { private readonly Declaration _declaration; private readonly IEnumerable _components; + private readonly BitmapImage _icon; private static readonly DeclarationType[] ComponentTypes = { @@ -25,10 +29,16 @@ public CodeExplorerProjectViewModel(Declaration declaration, IEnumerable grouping.Where(item => ComponentTypes.Contains(item.DeclarationType)) .Select(item => new CodeExplorerComponentViewModel(item, grouping))) + .OrderBy(item => item.Name) .ToList(); + + var isProtected = _declaration.Project.Protection == vbext_ProjectProtection.vbext_pp_locked; + _icon = GetImageSource(resx.folder_horizontal); } - public bool IsProtected { get { return _declaration.Project.Protection == vbext_ProjectProtection.vbext_pp_locked; } } public IEnumerable Components { get { return _components; } } + + public string Name { get { return _declaration.IdentifierName; } } + public BitmapImage Icon { get { return _icon; } } } } \ No newline at end of file diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs index 6146bd3f3f..225659acfb 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Collections.ObjectModel; using System.Linq; using System.Windows.Input; using Rubberduck.Parsing.Symbols; @@ -58,8 +59,8 @@ private set } } - private IEnumerable _projects; - public IEnumerable Projects + private ObservableCollection _projects; + public ObservableCollection Projects { get { return _projects; } set @@ -81,8 +82,8 @@ private void ParserState_StateChanged(object sender, ParserStateEventArgs e) .GroupBy(declaration => declaration.Project) .ToList(); - Projects = userDeclarations.Select(grouping => - new CodeExplorerProjectViewModel(grouping.Single(declaration => declaration.DeclarationType == DeclarationType.Project), grouping)); + Projects = new ObservableCollection(userDeclarations.Select(grouping => + new CodeExplorerProjectViewModel(grouping.Single(declaration => declaration.DeclarationType == DeclarationType.Project), grouping))); } private void ParserState_ModuleStateChanged(object sender, Parsing.ParseProgressEventArgs e) diff --git a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs index 9ca77307b4..6dbcf2a574 100644 --- a/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs +++ b/Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs @@ -191,6 +191,7 @@ private void SetCurrentScope() private void SetCurrentScope(Declaration procedureDeclaration, string name) { _currentScope = _qualifiedName + "." + name; + _parentDeclaration = procedureDeclaration; } public override void EnterOptionBaseStmt(VBAParser.OptionBaseStmtContext context) diff --git a/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs b/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs index 90f22721a9..2b70f1b0ae 100644 --- a/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs +++ b/Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs @@ -86,7 +86,7 @@ public void SetCurrentScope() public void SetCurrentScope(string memberName, DeclarationType? accessor = null) { - _currentScope = _declarations.Single(item => + _currentScope = _declarations.SingleOrDefault(item => _memberTypes.Contains(item.DeclarationType) && (!accessor.HasValue || item.DeclarationType == accessor.Value) && item.Project == _qualifiedModuleName.Project From 283f2e2a95d37883716df92440bc30dc77d559e6 Mon Sep 17 00:00:00 2001 From: Mathieu Guindon Date: Sun, 10 Jan 2016 22:51:33 -0500 Subject: [PATCH 17/18] fixed results sorting issue --- .../Inspections/CodeInspectionResultBase.cs | 13 ++++++++++++- .../Inspections/ICodeInspectionResult.cs | 2 +- RetailCoder.VBE/Inspections/IInspection.cs | 5 +++-- RetailCoder.VBE/Inspections/InspectionBase.cs | 12 ++++++++++++ .../CodeInspections/InspectionResultsControl.xaml | 7 +++++++ 5 files changed, 35 insertions(+), 4 deletions(-) diff --git a/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs b/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs index e057057c5e..8f330da302 100644 --- a/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs +++ b/RetailCoder.VBE/Inspections/CodeInspectionResultBase.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; using System.Linq; using Antlr4.Runtime; using Rubberduck.Parsing; @@ -82,6 +83,11 @@ public QualifiedSelection QualifiedSelection public virtual CodeInspectionQuickFix DefaultQuickFix { get { return QuickFixes.FirstOrDefault(); } } + public int CompareTo(ICodeInspectionResult other) + { + return Inspection.CompareTo(other.Inspection); + } + public override string ToString() { var module = QualifiedSelection.QualifiedName; @@ -94,6 +100,11 @@ public override string ToString() QualifiedSelection.Selection.StartLine); } + public int CompareTo(object obj) + { + return CompareTo(obj as ICodeInspectionResult); + } + public string ToCsvString() { var module = QualifiedSelection.QualifiedName; diff --git a/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs b/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs index b49cacd9bf..4cc2d9c94a 100644 --- a/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/ICodeInspectionResult.cs @@ -5,7 +5,7 @@ namespace Rubberduck.Inspections { - public interface ICodeInspectionResult + public interface ICodeInspectionResult : IComparable, IComparable { IEnumerable QuickFixes { get; } CodeInspectionQuickFix DefaultQuickFix { get; } diff --git a/RetailCoder.VBE/Inspections/IInspection.cs b/RetailCoder.VBE/Inspections/IInspection.cs index 0eceed32ab..6ecd408060 100644 --- a/RetailCoder.VBE/Inspections/IInspection.cs +++ b/RetailCoder.VBE/Inspections/IInspection.cs @@ -1,11 +1,12 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Rubberduck.Inspections { /// /// An interface that abstracts a runnable code inspection. /// - public interface IInspection : IInspectionModel + public interface IInspection : IInspectionModel, IComparable, IComparable { /// /// Runs code inspection on specified parse trees. diff --git a/RetailCoder.VBE/Inspections/InspectionBase.cs b/RetailCoder.VBE/Inspections/InspectionBase.cs index 685e0578a8..a5367fc921 100644 --- a/RetailCoder.VBE/Inspections/InspectionBase.cs +++ b/RetailCoder.VBE/Inspections/InspectionBase.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using System.Linq; using Rubberduck.Parsing.Symbols; @@ -20,6 +21,7 @@ protected InspectionBase(RubberduckParserState state) public virtual string Name { get { return GetType().Name; } } public virtual CodeInspectionSeverity Severity { get; set; } public virtual string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta"); } } + // ReSharper disable once UnusedMember.Global: it's referenced in xaml public virtual string InspectionTypeName { get { return InspectionsUI.ResourceManager.GetString(InspectionType.ToString()); } } public virtual string AnnotationName { get { return Name.Replace("Inspection", string.Empty); } } @@ -32,5 +34,15 @@ protected virtual IEnumerable UserDeclarations { get { return State.AllUserDeclarations.Where(declaration => !declaration.IsInspectionDisabled(AnnotationName)); } } + + public int CompareTo(IInspection other) + { + return string.Compare(InspectionType + Name, other.InspectionType + other.Name, StringComparison.Ordinal); + } + + public int CompareTo(object obj) + { + return CompareTo(obj as IInspection); + } } } \ No newline at end of file diff --git a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml index 8e2c114fd4..46b22c729a 100644 --- a/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml +++ b/RetailCoder.VBE/UI/CodeInspections/InspectionResultsControl.xaml @@ -7,6 +7,7 @@ xmlns:resx="clr-namespace:Rubberduck.UI" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:codeInspections="clr-namespace:Rubberduck.UI.CodeInspections" + xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance codeInspections:InspectionResultsViewModel}"> @@ -92,6 +93,9 @@ + + + @@ -99,6 +103,9 @@ + + + Date: Mon, 11 Jan 2016 01:17:10 -0500 Subject: [PATCH 18/18] non-nestable custom folders are now supported in Code Explorer. better than no custom folders at all! --- .../Inspections/InspectionsUI.Designer.cs | 16 +++---- .../Inspections/InspectionsUI.resx | 10 ++-- ...=> MultipleFolderAnnotationsInspection.cs} | 14 +++--- RetailCoder.VBE/Rubberduck.csproj | 2 +- .../CodeExplorerComponentViewModel.cs | 23 +++------- .../UI/CodeExplorer/CodeExplorerControl.xaml | 25 +++++++--- .../CodeExplorerProjectViewModel.cs | 46 ++++++++++++++++++- Rubberduck.Parsing/Grammar/Annotations.cs | 2 +- Rubberduck.Parsing/Symbols/Declaration.cs | 29 +++++++++++- 9 files changed, 118 insertions(+), 49 deletions(-) rename RetailCoder.VBE/Inspections/{MultipleNamespaceDeclarationInspection.cs => MultipleFolderAnnotationsInspection.cs} (66%) diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs index 73e5301557..8bd9d25b34 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs +++ b/RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs @@ -315,27 +315,27 @@ internal static string MultipleDeclarationsInspectionName { /// /// Looks up a localized string similar to '{0}' has more than one namespace declaration.. /// - internal static string MultipleNamespaceDeclarationInspection { + internal static string MultipleFolderAnnotationsInspection { get { - return ResourceManager.GetString("MultipleNamespaceDeclarationInspection", resourceCulture); + return ResourceManager.GetString("MultipleFolderAnnotationsInspection", resourceCulture); } } /// - /// Looks up a localized string similar to Rubberduck only uses the first '@Namespace' annotation in a code module; consider removing extraneous ones.. + /// Looks up a localized string similar to Rubberduck only uses the first '@Folder' annotation in a code module; consider removing extraneous ones.. /// - internal static string MultipleNamespaceDeclarationInspectionMeta { + internal static string MultipleFolderAnnotationsInspectionMeta { get { - return ResourceManager.GetString("MultipleNamespaceDeclarationInspectionMeta", resourceCulture); + return ResourceManager.GetString("MultipleFolderAnnotationsInspectionMeta", resourceCulture); } } /// - /// Looks up a localized string similar to Component has more than one namespace annotation.. + /// Looks up a localized string similar to Component has more than one folder annotation.. /// - internal static string MultipleNamespaceDeclarationInspectionName { + internal static string MultipleFolderAnnotationsInspectionName { get { - return ResourceManager.GetString("MultipleNamespaceDeclarationInspectionName", resourceCulture); + return ResourceManager.GetString("MultipleFolderAnnotationsInspectionName", resourceCulture); } } diff --git a/RetailCoder.VBE/Inspections/InspectionsUI.resx b/RetailCoder.VBE/Inspections/InspectionsUI.resx index 7816da9eab..9bcec43793 100644 --- a/RetailCoder.VBE/Inspections/InspectionsUI.resx +++ b/RetailCoder.VBE/Inspections/InspectionsUI.resx @@ -201,14 +201,14 @@ Instruction contains multiple declarations - + '{0}' has more than one namespace declaration. - - Rubberduck only uses the first '@Namespace' annotation in a code module; consider removing extraneous ones. + + Rubberduck only uses the first '@Folder' annotation in a code module; consider removing extraneous ones. - - Component has more than one namespace annotation. + + Component has more than one folder annotation. This is likely a bug. The return value of a function or property getter must be assigned before exiting, otherwise the program will not be working with expected results. If a function has no meaningful return value, consider declaring it as a 'Sub' procedure instead. diff --git a/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs b/RetailCoder.VBE/Inspections/MultipleFolderAnnotationsInspection.cs similarity index 66% rename from RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs rename to RetailCoder.VBE/Inspections/MultipleFolderAnnotationsInspection.cs index a6b530b5c4..dea500658e 100644 --- a/RetailCoder.VBE/Inspections/MultipleNamespaceDeclarationInspection.cs +++ b/RetailCoder.VBE/Inspections/MultipleFolderAnnotationsInspection.cs @@ -5,15 +5,15 @@ namespace Rubberduck.Inspections { - public sealed class MultipleNamespaceDeclarationInspection : InspectionBase + public sealed class MultipleFolderAnnotationsInspection : InspectionBase { - public MultipleNamespaceDeclarationInspection(RubberduckParserState state) + public MultipleFolderAnnotationsInspection(RubberduckParserState state) : base(state) { Severity = CodeInspectionSeverity.Warning; } - public override string Description { get { return InspectionsUI.MultipleNamespaceDeclarationInspection; } } + public override string Description { get { return InspectionsUI.MultipleFolderAnnotationsInspection; } } public override CodeInspectionType InspectionType { get { return CodeInspectionType.MaintainabilityAndReadabilityIssues; } } public override IEnumerable GetInspectionResults() @@ -23,15 +23,15 @@ public override IEnumerable GetInspectionResults() || declaration.DeclarationType == DeclarationType.Module) && declaration.Annotations.Split('\n').Count(annotation => annotation.StartsWith(Parsing.Grammar.Annotations.AnnotationMarker + - Parsing.Grammar.Annotations.Namespace)) > 1); + Parsing.Grammar.Annotations.Folder)) > 1); return issues.Select(issue => - new MultipleNamespaceDeclarationInspectionResult(this, string.Format(Description, issue.ComponentName), issue)); + new MultipleFolderAnnotationsInspectionResult(this, string.Format(Description, issue.ComponentName), issue)); } } - public class MultipleNamespaceDeclarationInspectionResult : CodeInspectionResultBase + public class MultipleFolderAnnotationsInspectionResult : CodeInspectionResultBase { - public MultipleNamespaceDeclarationInspectionResult(IInspection inspection, string result, Declaration target) + public MultipleFolderAnnotationsInspectionResult(IInspection inspection, string result, Declaration target) : base(inspection, result, target) { } diff --git a/RetailCoder.VBE/Rubberduck.csproj b/RetailCoder.VBE/Rubberduck.csproj index 570ab6199e..f13b1cffbb 100644 --- a/RetailCoder.VBE/Rubberduck.csproj +++ b/RetailCoder.VBE/Rubberduck.csproj @@ -304,7 +304,7 @@ True InspectionsUI.resx - + diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs index 63b2742356..8008b0c6b5 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerComponentViewModel.cs @@ -31,25 +31,12 @@ public CodeExplorerComponentViewModel(Declaration declaration, IEnumerable item.Scope) .SelectMany(grouping => - grouping.Where(item => item.ParentDeclaration.Equals(declaration) && MemberTypes.Contains(item.DeclarationType)) + grouping.Where(item => item.ParentDeclaration != null && item.ParentDeclaration.Equals(declaration) && MemberTypes.Contains(item.DeclarationType)) .Select(item => new CodeExplorerMemberViewModel(item, grouping))) .OrderBy(item => item.Name) .ToList(); - var ns = _declaration.Annotations - .Split('\n') - .FirstOrDefault(annotation => annotation.StartsWith(Parsing.Grammar.Annotations.AnnotationMarker + Parsing.Grammar.Annotations.Namespace)); - - if (ns != null) - { - - var value = ns.Split(' '); - _namespace = value.Length == 1 ? string.Empty : value[1]; - } - else - { - _namespace = string.Empty; - } + _customFolder = declaration.CustomFolder; } public IEnumerable Members { get { return _members; } } @@ -68,8 +55,10 @@ public bool IsTestModule public string Name { get { return _declaration.IdentifierName; } } - private readonly string _namespace; - public string Namespace { get { return _namespace; } } + private readonly string _customFolder; + public string CustomFolder { get { return _customFolder; } } + + public string TypeFolder { get { return DeclarationType.ToString(); } } private vbext_ComponentType ComponentType { get { return _declaration.QualifiedName.QualifiedModuleName.Component.Type; } } diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml index fd07b0e4b2..8bd89934ea 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerControl.xaml @@ -7,6 +7,7 @@ xmlns:symbols="clr-namespace:Rubberduck.Parsing.Symbols;assembly=Rubberduck.Parsing" xmlns:resx="clr-namespace:Rubberduck.UI" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" + xmlns:componentModel="clr-namespace:System.ComponentModel;assembly=WindowsBase" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" d:DataContext="{d:DesignInstance explorer:CodeExplorerViewModel}"> @@ -94,6 +95,13 @@ ItemTemplate="{StaticResource MemberItemTemplate}"> + + + + - - - - + + + - + @@ -137,7 +148,7 @@ - + @@ -154,7 +165,7 @@ HorizontalContentAlignment="Stretch" MouseDoubleClick="TreeView_OnMouseDoubleClick" ItemsSource="{Binding Projects}" - ItemTemplate="{StaticResource CodeExplorerTreeViewTemplate}"> + ItemTemplate="{StaticResource CodeExplorerCustomFoldersTemplate}"> diff --git a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs index 9a67937512..6b52fe8136 100644 --- a/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs +++ b/RetailCoder.VBE/UI/CodeExplorer/CodeExplorerProjectViewModel.cs @@ -12,6 +12,8 @@ public class CodeExplorerProjectViewModel : ViewModelBase { private readonly Declaration _declaration; private readonly IEnumerable _components; + private readonly IEnumerable _customFolders; + private readonly BitmapImage _icon; private static readonly DeclarationType[] ComponentTypes = @@ -25,20 +27,60 @@ public class CodeExplorerProjectViewModel : ViewModelBase public CodeExplorerProjectViewModel(Declaration declaration, IEnumerable declarations) { _declaration = declaration; - _components = declarations.GroupBy(item => item.ComponentName) + var items = declarations.ToList(); + + _components = items.GroupBy(item => item.ComponentName) .SelectMany(grouping => grouping.Where(item => ComponentTypes.Contains(item.DeclarationType)) .Select(item => new CodeExplorerComponentViewModel(item, grouping))) .OrderBy(item => item.Name) .ToList(); + _customFolders = items.GroupBy(item => item.CustomFolder) + .Select(grouping => new CodeExplorerCustomFolderViewModel(grouping.Key, grouping)) + .OrderBy(item => item.Name) + .ToList(); + var isProtected = _declaration.Project.Protection == vbext_ProjectProtection.vbext_pp_locked; _icon = GetImageSource(resx.folder_horizontal); } public IEnumerable Components { get { return _components; } } + public IEnumerable CustomFolders { get { return _customFolders; } } - public string Name { get { return _declaration.IdentifierName; } } + public string Name { get { return _declaration.CustomFolder; } } public BitmapImage Icon { get { return _icon; } } } + + public class CodeExplorerCustomFolderViewModel : ViewModelBase + { + private readonly string _name; + private readonly IEnumerable _components; + + private static readonly DeclarationType[] ComponentTypes = + { + DeclarationType.Class, + DeclarationType.Document, + DeclarationType.Module, + DeclarationType.UserForm, + }; + + public CodeExplorerCustomFolderViewModel(string name, IEnumerable declarations) + { + _name = name; + + var items = declarations.ToList(); + + _components = items.GroupBy(item => item.ComponentName) + .SelectMany(grouping => + grouping.Where(item => ComponentTypes.Contains(item.DeclarationType)) + .Select(item => new CodeExplorerComponentViewModel(item, grouping))) + .OrderBy(item => item.Name) + .ToList(); + } + + public string Name { get { return _name; } } + + public IEnumerable Components { get { return _components; } } + } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Grammar/Annotations.cs b/Rubberduck.Parsing/Grammar/Annotations.cs index 16752f4daf..fe6a39a2bf 100644 --- a/Rubberduck.Parsing/Grammar/Annotations.cs +++ b/Rubberduck.Parsing/Grammar/Annotations.cs @@ -6,6 +6,6 @@ public static class Annotations public static readonly string TestModule = "TestModule"; public static readonly string TestMethod = "TestMethod"; public static readonly string IgnoreInspection = "Ignore"; - public static readonly string Namespace = "Namespace"; + public static readonly string Folder = "Folder"; } } \ No newline at end of file diff --git a/Rubberduck.Parsing/Symbols/Declaration.cs b/Rubberduck.Parsing/Symbols/Declaration.cs index 415115e68f..17f2fd7394 100644 --- a/Rubberduck.Parsing/Symbols/Declaration.cs +++ b/Rubberduck.Parsing/Symbols/Declaration.cs @@ -40,6 +40,23 @@ public Declaration(QualifiedMemberName qualifiedName, Declaration parentDeclarat _context = context; _isBuiltIn = isBuiltIn; _annotations = annotations; + + _projectName = _qualifiedName.QualifiedModuleName.ProjectName; + + var ns = Annotations.Split('\n') + .FirstOrDefault(annotation => annotation.StartsWith(Grammar.Annotations.AnnotationMarker + Grammar.Annotations.Folder)); + + string result; + if (string.IsNullOrEmpty(ns)) + { + result = _projectName; + } + else + { + var value = ns.Split(' ')[1]; + result = value; + } + _customFolder = result; } /// @@ -160,10 +177,11 @@ public void AddMemberCall(IdentifierReference reference) /// public VBProject Project { get { return _qualifiedName.QualifiedModuleName.Project; } } + private readonly string _projectName; /// /// Gets the name of the VBProject the declaration is made in. /// - public string ProjectName { get { return _qualifiedName.QualifiedModuleName.ProjectName; } } + public string ProjectName { get { return _projectName; } } /// /// Gets the name of the VBComponent the declaration is made in. @@ -317,6 +335,15 @@ public string Scope } } + private readonly string _customFolder; + public string CustomFolder + { + get + { + return _customFolder; + } + } + public bool Equals(Declaration other) { return other.Project == Project