From 2be1449f6c41502817648272188eb797289a8be7 Mon Sep 17 00:00:00 2001 From: Abraham Hosch Date: Thu, 19 May 2016 09:12:25 -0500 Subject: [PATCH 1/7] This reverts commit 9f8ca02f44db637be3b44818f1a3c9e3f0a9e7f2. --- .../Inspections/ObsoleteTypeHintInspection.cs | 14 ++++---------- .../UntypedFunctionUsageInspectionResult.cs | 8 +++----- 2 files changed, 7 insertions(+), 15 deletions(-) diff --git a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs index 18d906b525..e59466226f 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs @@ -22,18 +22,12 @@ public override IEnumerable GetInspectionResults() var declarations = from item in results where item.HasTypeHint() - select new ObsoleteTypeHintInspectionResult(this, - string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, - InspectionsUI.Inspections_Declaration, item.DeclarationType.ToString().ToLower(), - item.IdentifierName), new QualifiedContext(item.QualifiedName, item.Context), item); - + // bug: this inspection result only has one value. Why are we passing two in? + select new ObsoleteTypeHintInspectionResult(this, string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, InspectionsUI.Inspections_Declaration, item.DeclarationType.ToString().ToLower(), item.IdentifierName), new QualifiedContext(item.QualifiedName, item.Context), item); + // todo: localize this InspectionResultFormat properly var references = from item in results.SelectMany(d => d.References) where item.HasTypeHint() - select new ObsoleteTypeHintInspectionResult(this, - string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, - InspectionsUI.Inspections_Usage, item.Declaration.DeclarationType.ToString().ToLower(), - item.IdentifierName), new QualifiedContext(item.QualifiedModuleName, item.Context), - item.Declaration); + select new ObsoleteTypeHintInspectionResult(this, string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, InspectionsUI.Inspections_Usage, item.Declaration.DeclarationType.ToString().ToLower(), item.IdentifierName), new QualifiedContext(item.QualifiedModuleName, item.Context), item.Declaration); return declarations.Union(references); } diff --git a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs index 7f6f8e1bdc..ac8dd67c77 100644 --- a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs @@ -32,20 +32,18 @@ public override string Description public class UntypedFunctionUsageQuickFix : CodeInspectionQuickFix { public UntypedFunctionUsageQuickFix(ParserRuleContext context, QualifiedSelection selection) - : base(context, selection, - string.Format(InspectionsUI.QuickFixUseTypedFunction_, - context.GetText(), context.GetText().Insert(context.GetText().IndexOf('('), "$"))) + : base(context, selection, string.Format(InspectionsUI.QuickFixUseTypedFunction_, context.GetText(), context.GetText() + "$")) { } public override void Fix() { var originalInstruction = Context.GetText(); - var newInstruction = originalInstruction.Insert(originalInstruction.IndexOf('('), "$"); + var newInstruction = originalInstruction + "$"; var selection = Selection.Selection; var module = Selection.QualifiedName.Component.CodeModule; - var lines = module.Lines[selection.StartLine, selection.LineCount]; + var lines = module.get_Lines(selection.StartLine, selection.LineCount); var result = lines.Replace(originalInstruction, newInstruction); module.ReplaceLine(selection.StartLine, result); From 580f6e970af36da47e79b7d5a125edfb95530da8 Mon Sep 17 00:00:00 2001 From: Abraham Hosch Date: Thu, 19 May 2016 10:01:05 -0500 Subject: [PATCH 2/7] Close #1537 --- .../UntypedFunctionUsageInspectionResult.cs | 39 ++++++++++++++++--- 1 file changed, 34 insertions(+), 5 deletions(-) diff --git a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs index ac8dd67c77..1120a68d52 100644 --- a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs @@ -1,5 +1,8 @@ +using System; using System.Collections.Generic; +using System.Linq; using Antlr4.Runtime; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Symbols; using Rubberduck.VBEditor; @@ -16,7 +19,7 @@ public UntypedFunctionUsageInspectionResult(IInspection inspection, IdentifierRe _reference = reference; _quickFixes = new CodeInspectionQuickFix[] { - new UntypedFunctionUsageQuickFix(Context, QualifiedSelection), + new UntypedFunctionUsageQuickFix((ParserRuleContext)GetFirst(typeof(VBAParser.IdentifierContext)).Parent, QualifiedSelection), new IgnoreOnceQuickFix(Context, QualifiedSelection, Inspection.AnnotationName), }; } @@ -27,27 +30,53 @@ public override string Description { get { return string.Format(Inspection.Description, _reference.Declaration.IdentifierName); } } + + private ParserRuleContext GetFirst(Type nodeType) + { + var unexploredNodes = new List {Context}; + + while (unexploredNodes.Any()) + { + if (unexploredNodes[0].GetType() == nodeType) + { + return unexploredNodes[0]; + } + + unexploredNodes.AddRange(unexploredNodes[0].children.OfType()); + unexploredNodes.RemoveAt(0); + } + + return null; + } } public class UntypedFunctionUsageQuickFix : CodeInspectionQuickFix { public UntypedFunctionUsageQuickFix(ParserRuleContext context, QualifiedSelection selection) - : base(context, selection, string.Format(InspectionsUI.QuickFixUseTypedFunction_, context.GetText(), context.GetText() + "$")) + : base(context, selection, string.Format(InspectionsUI.QuickFixUseTypedFunction_, context.GetText(), GetNewSignature(context))) { } public override void Fix() { var originalInstruction = Context.GetText(); - var newInstruction = originalInstruction + "$"; + var newInstruction = GetNewSignature(Context); var selection = Selection.Selection; var module = Selection.QualifiedName.Component.CodeModule; - var lines = module.get_Lines(selection.StartLine, selection.LineCount); + var lines = module.Lines[selection.StartLine, selection.LineCount]; var result = lines.Replace(originalInstruction, newInstruction); module.ReplaceLine(selection.StartLine, result); - // FIXME trigger reparse + } + + private static string GetNewSignature(ParserRuleContext context) + { + return context.children.Aggregate(string.Empty, (current, member) => + { + var isIdentifierNode = member is VBAParser.IdentifierContext; + return current + member.GetText() + (isIdentifierNode ? "$" : string.Empty); + }); } } } From 412d4c9a21052cbe40d066eed9cccabed03334a1 Mon Sep 17 00:00:00 2001 From: Abraham Hosch Date: Thu, 19 May 2016 14:01:22 -0500 Subject: [PATCH 3/7] Remove unneeded comments and format code for Obsolete Type Hint. Add Assert to Untyped Function Usage. --- .../Inspections/ObsoleteTypeHintInspection.cs | 16 ++++++++++++---- .../UntypedFunctionUsageInspectionResult.cs | 3 +++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs index e59466226f..99bbeb4349 100644 --- a/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs +++ b/RetailCoder.VBE/Inspections/ObsoleteTypeHintInspection.cs @@ -22,12 +22,20 @@ public override IEnumerable GetInspectionResults() var declarations = from item in results where item.HasTypeHint() - // bug: this inspection result only has one value. Why are we passing two in? - select new ObsoleteTypeHintInspectionResult(this, string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, InspectionsUI.Inspections_Declaration, item.DeclarationType.ToString().ToLower(), item.IdentifierName), new QualifiedContext(item.QualifiedName, item.Context), item); - // todo: localize this InspectionResultFormat properly + select + new ObsoleteTypeHintInspectionResult(this, + string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, + InspectionsUI.Inspections_Declaration, item.DeclarationType.ToString().ToLower(), + item.IdentifierName), new QualifiedContext(item.QualifiedName, item.Context), item); + var references = from item in results.SelectMany(d => d.References) where item.HasTypeHint() - select new ObsoleteTypeHintInspectionResult(this, string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, InspectionsUI.Inspections_Usage, item.Declaration.DeclarationType.ToString().ToLower(), item.IdentifierName), new QualifiedContext(item.QualifiedModuleName, item.Context), item.Declaration); + select + new ObsoleteTypeHintInspectionResult(this, + string.Format(InspectionsUI.ObsoleteTypeHintInspectionResultFormat, + InspectionsUI.Inspections_Usage, item.Declaration.DeclarationType.ToString().ToLower(), + item.IdentifierName), new QualifiedContext(item.QualifiedModuleName, item.Context), + item.Declaration); return declarations.Union(references); } diff --git a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs index 1120a68d52..102c094ba5 100644 --- a/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs +++ b/RetailCoder.VBE/Inspections/UntypedFunctionUsageInspectionResult.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Antlr4.Runtime; using Rubberduck.Parsing.Grammar; @@ -72,6 +73,8 @@ public override void Fix() private static string GetNewSignature(ParserRuleContext context) { + Debug.Assert(context != null); + return context.children.Aggregate(string.Empty, (current, member) => { var isIdentifierNode = member is VBAParser.IdentifierContext; From 491e3fe137207ae77e1561c6cba01e2bf28766da Mon Sep 17 00:00:00 2001 From: comintern Date: Thu, 19 May 2016 21:36:27 -0500 Subject: [PATCH 4/7] Indenter fixes for creeping comments, line continuations. Also release COM objects. Closes #1508 (#1549) * Fixed RootElement bug in XmlPersistanceService * Release COM objects in ReferencedDeclarationsCollector, Fix EOL comments and line continuations in Indenter. --- .../UI/Command/RunAllTestsCommand.cs | 2 +- .../ReferencedDeclarationsCollector.cs | 3 ++ Rubberduck.SmartIndenter/Indenter.cs | 33 +++++++++++-------- 3 files changed, 24 insertions(+), 14 deletions(-) diff --git a/RetailCoder.VBE/UI/Command/RunAllTestsCommand.cs b/RetailCoder.VBE/UI/Command/RunAllTestsCommand.cs index 918fc30c9d..0e997f5267 100644 --- a/RetailCoder.VBE/UI/Command/RunAllTestsCommand.cs +++ b/RetailCoder.VBE/UI/Command/RunAllTestsCommand.cs @@ -59,7 +59,7 @@ protected virtual void OnRunCompleted(TestRunEventArgs e) } } - public struct TestRunEventArgs + public class TestRunEventArgs { public long Duration { get; private set; } diff --git a/Rubberduck.Parsing/Symbols/ReferencedDeclarationsCollector.cs b/Rubberduck.Parsing/Symbols/ReferencedDeclarationsCollector.cs index 243c64084b..92853c5189 100644 --- a/Rubberduck.Parsing/Symbols/ReferencedDeclarationsCollector.cs +++ b/Rubberduck.Parsing/Symbols/ReferencedDeclarationsCollector.cs @@ -174,6 +174,7 @@ public IEnumerable GetDeclarationsForReference(Reference reference) info.GetTypeAttr(out typeAttributesPointer); var typeAttributes = (TYPEATTR)Marshal.PtrToStructure(typeAttributesPointer, typeof(TYPEATTR)); + info.ReleaseTypeAttr(typeAttributesPointer); var attributes = new Attributes(); if (typeAttributes.wTypeFlags.HasFlag(TYPEFLAGS.TYPEFLAG_FPREDECLID)) @@ -243,6 +244,7 @@ private Declaration CreateMemberDeclaration(out FUNCDESC memberDescriptor, TYPEK IntPtr memberDescriptorPointer; info.GetFuncDesc(memberIndex, out memberDescriptorPointer); memberDescriptor = (FUNCDESC)Marshal.PtrToStructure(memberDescriptorPointer, typeof(FUNCDESC)); + info.ReleaseFuncDesc(memberDescriptorPointer); if (memberDescriptor.callconv != CALLCONV.CC_STDCALL) { @@ -390,6 +392,7 @@ private Declaration CreateFieldDeclaration(ITypeInfo info, int fieldIndex, Decla info.GetVarDesc(fieldIndex, out ppVarDesc); var varDesc = (VARDESC)Marshal.PtrToStructure(ppVarDesc, typeof(VARDESC)); + info.ReleaseVarDesc(ppVarDesc); var names = new string[255]; int namesArrayLength; diff --git a/Rubberduck.SmartIndenter/Indenter.cs b/Rubberduck.SmartIndenter/Indenter.cs index 3d8f2d129f..c14cd95625 100644 --- a/Rubberduck.SmartIndenter/Indenter.cs +++ b/Rubberduck.SmartIndenter/Indenter.cs @@ -48,6 +48,11 @@ private void OnReportProgress(string moduleName, int progress, int max) public void IndentCurrentProcedure() { var pane = _vbe.ActiveCodePane; + + if (pane == null) + { + return; + } var module = pane.CodeModule; var selection = GetSelection(pane); @@ -69,6 +74,10 @@ public void IndentCurrentProcedure() public void IndentCurrentModule() { var pane = _vbe.ActiveCodePane; + if (pane == null) + { + return; + } Indent(pane.CodeModule.Parent); } @@ -288,12 +297,12 @@ public void Indent(string[] codeLines, string moduleName, bool reportProgress = break; case ": ": - // a multi-statement line separator => tidy up and continue - if (!currentLine.Substring(0, scan + 1).EndsWith("Then:")) + //a multi-statement line separator => tidy up and continue + if (!currentLine.Substring(0, scan + 1).EndsWith(" Then:")) { - currentLine = currentLine.Substring(0, scan + 1) + currentLine.Substring(scan + 2); + currentLine = currentLine.Substring(0, scan + 2) + currentLine.Substring(scan + 2); // check the indenting for the line segment - CheckLine(settings, currentLine, ref noIndent, out ins, out outs, ref atProcedureStart, ref atFirstProcLine, ref isInsideIfBlock); + CheckLine(settings, currentLine.Substring(start - 1), ref noIndent, out ins, out outs, ref atProcedureStart, ref atFirstProcLine, ref isInsideIfBlock); if (atProcedureStart) { atFirstDim = true; @@ -455,11 +464,7 @@ public void Indent(string[] codeLines, string moduleName, bool reportProgress = (settings.EndOfLineCommentStyle == EndOfLineCommentStyle.Absolute || settings.EndOfLineCommentStyle == EndOfLineCommentStyle.AlignInColumn)) { - gap -= lineNumber.Length - indents*settings.IndentSpaces - 1; - } - if (gap < 2) - { - gap = settings.IndentSpaces; + gap -= lineNumber.Length - indents * settings.IndentSpaces - 1; } commentStart = currentLine.Length + gap; @@ -467,15 +472,15 @@ public void Indent(string[] codeLines, string moduleName, bool reportProgress = } // work out where the text of the comment starts, to align the next line - if (currentLine.Substring(commentStart, 4) == "Rem ") + if (commentStart < currentLine.Length - 4 && currentLine.Substring(commentStart, 4) == "Rem ") { commentStart += 3; } - if (currentLine.Substring(commentStart, 1) == "'") + if (commentStart < currentLine.Length && currentLine.Substring(commentStart, 1) == "'") { commentStart += 1; } - while (currentLine.Substring(commentStart, 1) != " ") + while (commentStart < currentLine.Length && currentLine.Substring(commentStart, 1) != " ") { commentStart += 1; } @@ -528,7 +533,9 @@ public void Indent(string[] codeLines, string moduleName, bool reportProgress = atProcedureStart = false; } - CheckLine(settings, currentLine.Substring(start - 1, scan - 1), ref noIndent, out ins, out outs, ref atProcedureStart, ref atFirstProcLine, ref isInsideIfBlock); + CheckLine(settings, currentLine.Substring(start - 1, Math.Min(scan - 1, currentLine.Length - start)), + ref noIndent, out ins, out outs, ref atProcedureStart, ref atFirstProcLine, + ref isInsideIfBlock); if (atProcedureStart) { atFirstDim = true; From 42636ca506f108f4e4277995cbf6bae365bb23a4 Mon Sep 17 00:00:00 2001 From: Hosch250 Date: Fri, 20 May 2016 00:28:34 -0500 Subject: [PATCH 5/7] Fix Object Variable Not Set false positives (#1545) * Close #1530 * Fix failing test --- .../ObjectVariableNotSetInspection.cs | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/RetailCoder.VBE/Inspections/ObjectVariableNotSetInspection.cs b/RetailCoder.VBE/Inspections/ObjectVariableNotSetInspection.cs index fc3db24454..d56f91bc18 100644 --- a/RetailCoder.VBE/Inspections/ObjectVariableNotSetInspection.cs +++ b/RetailCoder.VBE/Inspections/ObjectVariableNotSetInspection.cs @@ -47,7 +47,7 @@ public SetObjectVariableQuickFix(IdentifierReference reference) public override void Fix() { var codeModule = Selection.QualifiedName.Component.CodeModule; - var codeLine = codeModule.get_Lines(Selection.Selection.StartLine, 1); + var codeLine = codeModule.Lines[Selection.Selection.StartLine, 1]; var letStatementLeftSide = Context.GetText(); var setStatementLeftSide = Tokens.Set + ' ' + letStatementLeftSide; @@ -86,19 +86,26 @@ public ObjectVariableNotSetInspection(RubberduckParserState state) public override IEnumerable GetInspectionResults() { - return State.AllUserDeclarations - .Where(item => !ValueTypes.Contains(item.AsTypeName) - && !item.IsSelfAssigned - && (item.DeclarationType == DeclarationType.Variable - || item.DeclarationType == DeclarationType.Parameter)) + var interestingDeclarations = + State.AllUserDeclarations.Where(item => + !item.IsSelfAssigned && + !ValueTypes.Contains(item.AsTypeName) && + (item.AsTypeDeclaration == null || + item.AsTypeDeclaration.DeclarationType != DeclarationType.Enumeration && + item.AsTypeDeclaration.DeclarationType != DeclarationType.UserDefinedType) && + (item.DeclarationType == DeclarationType.Variable || + item.DeclarationType == DeclarationType.Parameter)); + + var interestingReferences = interestingDeclarations .SelectMany(declaration => declaration.References.Where(reference => { - var k = reference.Context.parent.GetType(); var setStmtContext = ParserRuleContextHelper.GetParent(reference.Context); - return setStmtContext != null && setStmtContext.LET() == null; - })) - .Select(reference => new ObjectVariableNotSetInspectionResult(this, reference)); + return reference.IsAssignment && setStmtContext != null && setStmtContext.LET() == null; + })); + + + return interestingReferences.Select(reference => new ObjectVariableNotSetInspectionResult(this, reference)); } } } From 23f2796cdf9395649e110f6de2c20a7531a22370 Mon Sep 17 00:00:00 2001 From: Hosch250 Date: Fri, 20 May 2016 00:28:46 -0500 Subject: [PATCH 6/7] Close #1546 (#1548) --- .../UI/Command/IndentCurrentProcedureCommand.cs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/RetailCoder.VBE/UI/Command/IndentCurrentProcedureCommand.cs b/RetailCoder.VBE/UI/Command/IndentCurrentProcedureCommand.cs index d054f5abb7..ca31332d36 100644 --- a/RetailCoder.VBE/UI/Command/IndentCurrentProcedureCommand.cs +++ b/RetailCoder.VBE/UI/Command/IndentCurrentProcedureCommand.cs @@ -1,4 +1,6 @@ using System.Runtime.InteropServices; +using Microsoft.Vbe.Interop; +using Rubberduck.Parsing.VBA; using Rubberduck.Settings; using Rubberduck.SmartIndenter; @@ -7,13 +9,22 @@ namespace Rubberduck.UI.Command [ComVisible(false)] public class IndentCurrentProcedureCommand : CommandBase { + private readonly VBE _vbe; + private readonly RubberduckParserState _state; private readonly IIndenter _indenter; - public IndentCurrentProcedureCommand(IIndenter indenter) + public IndentCurrentProcedureCommand(VBE vbe, RubberduckParserState state, IIndenter indenter) { + _vbe = vbe; + _state = state; _indenter = indenter; } + public override bool CanExecute(object parameter) + { + return _state.FindSelectedDeclaration(_vbe.ActiveCodePane, true) != null; + } + public override void Execute(object parameter) { _indenter.IndentCurrentProcedure(); From f56a634993908468e0ba2c43d827eb3cc5a973d9 Mon Sep 17 00:00:00 2001 From: Hosch250 Date: Fri, 20 May 2016 00:29:04 -0500 Subject: [PATCH 7/7] Code Explorer #1513 (#1547) * Close #1513 * Fix failing tests. Add more. --- .../CodeExplorer/CodeExplorerItemViewModel.cs | 24 +++ .../CodeExplorer/CodeExplorerTests.cs | 191 +++++++++++++++++- 2 files changed, 209 insertions(+), 6 deletions(-) diff --git a/RetailCoder.VBE/Navigation/CodeExplorer/CodeExplorerItemViewModel.cs b/RetailCoder.VBE/Navigation/CodeExplorer/CodeExplorerItemViewModel.cs index d7e7b474e1..4d2d2a3ffd 100644 --- a/RetailCoder.VBE/Navigation/CodeExplorer/CodeExplorerItemViewModel.cs +++ b/RetailCoder.VBE/Navigation/CodeExplorer/CodeExplorerItemViewModel.cs @@ -28,6 +28,22 @@ public override int Compare(CodeExplorerItemViewModel x, CodeExplorerItemViewMod public class CompareByType : Comparer { + private static readonly Dictionary SortOrder = new Dictionary + { + {DeclarationType.LibraryFunction, 0}, + {DeclarationType.LibraryProcedure, 1}, + {DeclarationType.UserDefinedType, 2}, + {DeclarationType.Enumeration, 3}, + {DeclarationType.Event, 4}, + {DeclarationType.Constant, 5}, + {DeclarationType.Variable, 6}, + {DeclarationType.PropertyGet, 7}, + {DeclarationType.PropertyLet, 8}, + {DeclarationType.PropertySet, 9}, + {DeclarationType.Function, 10}, + {DeclarationType.Procedure, 11} + }; + public override int Compare(CodeExplorerItemViewModel x, CodeExplorerItemViewModel y) { if (x == y) @@ -54,6 +70,14 @@ public override int Compare(CodeExplorerItemViewModel x, CodeExplorerItemViewMod // keep separate types separate if (xNode.Declaration.DeclarationType != yNode.Declaration.DeclarationType) { + int xValue, yValue; + + if (SortOrder.TryGetValue(xNode.Declaration.DeclarationType, out xValue) && + SortOrder.TryGetValue(yNode.Declaration.DeclarationType, out yValue)) + { + return xValue < yValue ? -1 : 1; + } + return xNode.Declaration.DeclarationType < yNode.Declaration.DeclarationType ? -1 : 1; } diff --git a/RubberduckTests/CodeExplorer/CodeExplorerTests.cs b/RubberduckTests/CodeExplorer/CodeExplorerTests.cs index d0b4b2339e..4539f0dd77 100644 --- a/RubberduckTests/CodeExplorer/CodeExplorerTests.cs +++ b/RubberduckTests/CodeExplorer/CodeExplorerTests.cs @@ -1038,13 +1038,192 @@ public void CompareByType_ReturnsZeroForErrorNodes() } [TestMethod] - public void CompareByType_ReturnsFieldBelowSub() + public void CompareByType_ReturnsEventAboveConst() { var inputCode = -@"Public Foo As Boolean +@"Public Event Foo(ByVal arg1 As Integer, ByVal arg2 As String) +Public Const Bar = 0"; -Sub Bar() -End Sub"; + var builder = new MockVbeBuilder(); + VBComponent component; + var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); + var mockHost = new Mock(); + mockHost.SetupAllProperties(); + + var state = new RubberduckParserState(); + var commands = new List(); + + var vm = new CodeExplorerViewModel(new FolderHelper(state, GetDelimiterConfigLoader()), state, commands); + + var parser = MockParser.Create(vbe.Object, state); + parser.Parse(); + + var eventNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo"); + var constNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Bar = 0"); + + Assert.AreEqual(-1, new CompareByType().Compare(eventNode, constNode)); + } + + [TestMethod] + public void CompareByType_ReturnsConstAboveField() + { + var inputCode = +@"Public Const Foo = 0 +Public Bar As Boolean"; + + var builder = new MockVbeBuilder(); + VBComponent component; + var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); + var mockHost = new Mock(); + mockHost.SetupAllProperties(); + + var state = new RubberduckParserState(); + var commands = new List(); + + var vm = new CodeExplorerViewModel(new FolderHelper(state, GetDelimiterConfigLoader()), state, commands); + + var parser = MockParser.Create(vbe.Object, state); + parser.Parse(); + + var constNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo = 0"); + var fieldNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Bar"); + + Assert.AreEqual(-1, new CompareByType().Compare(constNode, fieldNode)); + } + + [TestMethod] + public void CompareByType_ReturnsFieldAbovePropertyGet() + { + var inputCode = +@"Private Bar As Boolean + +Public Property Get Foo() As Variant +End Property +"; + + var builder = new MockVbeBuilder(); + VBComponent component; + var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); + var mockHost = new Mock(); + mockHost.SetupAllProperties(); + + var state = new RubberduckParserState(); + var commands = new List(); + + var vm = new CodeExplorerViewModel(new FolderHelper(state, GetDelimiterConfigLoader()), state, commands); + + var parser = MockParser.Create(vbe.Object, state); + parser.Parse(); + + var fieldNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Bar"); + var propertyGetNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo (Get)"); + + Assert.AreEqual(-1, new CompareByType().Compare(fieldNode, propertyGetNode)); + } + + [TestMethod] + public void CompareByType_ReturnsPropertyGetAbovePropertyLet() + { + var inputCode = +@"Public Property Get Foo() As Variant +End Property + +Public Property Let Foo(ByVal Value As Variant) +End Property +"; + + var builder = new MockVbeBuilder(); + VBComponent component; + var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); + var mockHost = new Mock(); + mockHost.SetupAllProperties(); + + var state = new RubberduckParserState(); + var commands = new List(); + + var vm = new CodeExplorerViewModel(new FolderHelper(state, GetDelimiterConfigLoader()), state, commands); + + var parser = MockParser.Create(vbe.Object, state); + parser.Parse(); + + var propertyGetNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo (Get)"); + var propertyLetNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo (Let)"); + + Assert.AreEqual(-1, new CompareByType().Compare(propertyGetNode, propertyLetNode)); + } + + [TestMethod] + public void CompareByType_ReturnsPropertyLetAbovePropertySet() + { + var inputCode = +@"Public Property Let Foo(ByVal Value As Variant) +End Property + +Public Property Set Foo(ByVal Value As Variant) +End Property +"; + + var builder = new MockVbeBuilder(); + VBComponent component; + var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); + var mockHost = new Mock(); + mockHost.SetupAllProperties(); + + var state = new RubberduckParserState(); + var commands = new List(); + + var vm = new CodeExplorerViewModel(new FolderHelper(state, GetDelimiterConfigLoader()), state, commands); + + var parser = MockParser.Create(vbe.Object, state); + parser.Parse(); + + var propertyLetNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo (Let)"); + var propertySetNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo (Set)"); + + Assert.AreEqual(-1, new CompareByType().Compare(propertyLetNode, propertySetNode)); + } + + [TestMethod] + public void CompareByType_ReturnsPropertySetAboveFunction() + { + var inputCode = +@"Public Property Set Foo(ByVal Value As Variant) +End Property + +Public Function Bar() As Boolean +End Function +"; + + var builder = new MockVbeBuilder(); + VBComponent component; + var vbe = builder.BuildFromSingleStandardModule(inputCode, out component); + var mockHost = new Mock(); + mockHost.SetupAllProperties(); + + var state = new RubberduckParserState(); + var commands = new List(); + + var vm = new CodeExplorerViewModel(new FolderHelper(state, GetDelimiterConfigLoader()), state, commands); + + var parser = MockParser.Create(vbe.Object, state); + parser.Parse(); + + var propertySetNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo (Set)"); + var functionNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Bar"); + + Assert.AreEqual(-1, new CompareByType().Compare(propertySetNode, functionNode)); + } + + [TestMethod] + public void CompareByType_ReturnsFunctionAboveSub() + { + var inputCode = +@"Public Function Foo() As Boolean +End Function + +Public Sub Bar() +End Sub +"; var builder = new MockVbeBuilder(); VBComponent component; @@ -1060,10 +1239,10 @@ Sub Bar() var parser = MockParser.Create(vbe.Object, state); parser.Parse(); + var functionNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo"); var subNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Bar"); - var fieldNode = vm.Projects.First().Items.First().Items.First().Items.Single(s => s.Name == "Foo"); - Assert.AreEqual(-1, new CompareByType().Compare(subNode, fieldNode)); + Assert.AreEqual(-1, new CompareByType().Compare(functionNode, subNode)); } [TestMethod]