Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
776904b
First refactoring of Parse and ParseAll
MDoerner Jan 27, 2017
1dcc114
Generate task to capture component parser result to allow to push the…
MDoerner Jan 28, 2017
4343e99
Refactor (fix) MemberNotOnInterfaceInspection to collect Declarations…
comintern Jan 28, 2017
7dbac24
Implement ApplicationWorksheetFunctionInspection.
comintern Jan 28, 2017
91668fd
Made ParseComponents use Parallel.ForEach with MaxDegreeOfParallelism
MDoerner Jan 28, 2017
2d24355
Forgot to override QualifiedSelection in ApplicationWorksheetFunction…
comintern Jan 29, 2017
0e4e331
Add quick fix warning to ApplicationWorksheetFunctionInspectionMeta
comintern Jan 29, 2017
c5481ff
Resolve AsTypeNames for UserForm controls.
comintern Jan 29, 2017
bf65bf0
Set MaxDegreeOfParserParallelism to universally acceptable value.
MDoerner Jan 29, 2017
3fe56a2
Repaired optimization not to parse unaltered components that got lost…
MDoerner Jan 29, 2017
878164a
Merge remote-tracking branch 'upstream/next' into ReworkParseCoordina…
MDoerner Jan 29, 2017
5384836
Only discover ProjectDisplayName when absolutely necessary.
comintern Jan 29, 2017
69f200e
Merge pull request #2588 from comintern/next
retailcoder Jan 29, 2017
d90bb6c
Fix IsImplicitByRef flags for built-in parameters.
comintern Jan 29, 2017
22c5da1
Merge branch 'next' into ReworkParseCoordinatorPart1
retailcoder Jan 29, 2017
78f8548
Merge branch 'next' into next
comintern Jan 29, 2017
1d8510c
Merge pull request #2590 from comintern/next
retailcoder Jan 29, 2017
da98049
Merge branch 'next' into ReworkParseCoordinatorPart1
retailcoder Jan 29, 2017
368b120
Merge pull request #2589 from MDoerner/ReworkParseCoordinatorPart1
retailcoder Jan 29, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions RetailCoder.VBE/Inspections/Abstract/InspectionResultBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,18 @@ public virtual int CompareTo(IInspectionResult other)
return Inspection.CompareTo(other.Inspection);
}

public override string ToString()
{
var module = QualifiedSelection.QualifiedName;
return string.Format(
InspectionsUI.QualifiedSelectionInspection,
Inspection.Severity,
Description,
"(" + module.ProjectDisplayName + ")",
module.ProjectName,
module.ComponentName,
QualifiedSelection.Selection.StartLine);
}
//public override string ToString()
//{
// var module = QualifiedSelection.QualifiedName;
// return string.Format(
// InspectionsUI.QualifiedSelectionInspection,
// Inspection.Severity,
// Description,
// "(" + module.ProjectDisplayName + ")",
// module.ProjectName,
// module.ComponentName,
// QualifiedSelection.Selection.StartLine);
//}

public virtual NavigateCodeEventArgs GetNavigationArgs()
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Collections.Generic;
using System.Linq;
using Rubberduck.Inspections.Abstract;
using Rubberduck.Inspections.Resources;
using Rubberduck.Inspections.Results;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.VBEditor;

namespace Rubberduck.Inspections
{
public class ApplicationWorksheetFunctionInspection : InspectionBase
{
public ApplicationWorksheetFunctionInspection(RubberduckParserState state)
: base(state, CodeInspectionSeverity.Suggestion)
{ }

public override string Meta { get { return InspectionsUI.ApplicationWorksheetFunctionInspectionMeta; } }
public override string Description { get { return InspectionsUI.ApplicationWorksheetFunctionInspectionName; } }
public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } }

public override IEnumerable<InspectionResultBase> GetInspectionResults()
{
var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => item.IsBuiltIn && item.IdentifierName == "Excel");
if (excel == null) { return Enumerable.Empty<InspectionResultBase>(); }

var members = new HashSet<string>(BuiltInDeclarations.Where(decl => decl.DeclarationType == DeclarationType.Function &&
decl.ParentDeclaration != null &&
decl.ParentDeclaration.ComponentName.Equals("WorksheetFunction"))
.Select(decl => decl.IdentifierName));

var usages = BuiltInDeclarations.Where(decl => decl.References.Any() &&
decl.ProjectName.Equals("Excel") &&
decl.ComponentName.Equals("Application") &&
members.Contains(decl.IdentifierName));

return (from usage in usages
from reference in usage.References.Where(use => !IsIgnoringInspectionResultFor(use, AnnotationName))
let qualifiedSelection = new QualifiedSelection(reference.QualifiedModuleName, reference.Selection)
select new ApplicationWorksheetFunctionInspectionResult(this, qualifiedSelection, usage.IdentifierName));
}
}
}
66 changes: 12 additions & 54 deletions RetailCoder.VBE/Inspections/MemberNotOnInterfaceInspection.cs
Original file line number Diff line number Diff line change
@@ -1,26 +1,15 @@
using System;
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Antlr4.Runtime;
using Rubberduck.Inspections.Abstract;
using Rubberduck.Inspections.Resources;
using Rubberduck.Inspections.Results;
using Rubberduck.Parsing;
using Rubberduck.Parsing.Grammar;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.VBEditor;

namespace Rubberduck.Inspections
{
public sealed class MemberNotOnInterfaceInspection : InspectionBase
{
private static readonly List<Type> InterestingTypes = new List<Type>
{
typeof(VBAParser.MemberAccessExprContext),
typeof(VBAParser.WithMemberAccessExprContext)
};

public MemberNotOnInterfaceInspection(RubberduckParserState state, CodeInspectionSeverity defaultSeverity = CodeInspectionSeverity.Warning)
: base(state, defaultSeverity)
{
Expand All @@ -32,51 +21,20 @@ public MemberNotOnInterfaceInspection(RubberduckParserState state, CodeInspectio

public override IEnumerable<InspectionResultBase> GetInspectionResults()
{
var unresolved = State.DeclarationFinder.UnresolvedMemberDeclarations().Where(decl => !IsIgnoringInspectionResultFor(decl, AnnotationName)).ToList();

var targets = Declarations.Where(decl => decl.AsTypeDeclaration != null &&
decl.ParentDeclaration.DeclarationType != DeclarationType.Project &&
decl.AsTypeDeclaration.IsBuiltIn &&
decl.AsTypeDeclaration.DeclarationType == DeclarationType.ClassModule &&
((ClassModuleDeclaration)decl.AsTypeDeclaration).IsExtensible &&
decl.References.Any(usage => InterestingTypes.Contains(usage.Context.Parent.GetType())))
.ToList();
((ClassModuleDeclaration)decl.AsTypeDeclaration).IsExtensible)
.SelectMany(decl => decl.References).ToList();

//Unfortunately finding implemented members is fairly expensive, so group by the return type.
return (from access in targets.GroupBy(t => t.AsTypeDeclaration)
let typeDeclaration = access.Key
let typeMembers = new HashSet<string>(BuiltInDeclarations.Where(d => d.ParentDeclaration != null && d.ParentDeclaration.Equals(typeDeclaration))
.Select(d => d.IdentifierName)
.Distinct())
from references in access.Select(usage => usage.References.Where(r => InterestingTypes.Contains(r.Context.Parent.GetType())))
from reference in references.Where(r => !r.IsIgnoringInspectionResultFor(AnnotationName))
let identifier = reference.Context.Parent.GetChild(reference.Context.Parent.ChildCount - 1)
where !typeMembers.Contains(identifier.GetText())
let pseudoDeclaration = CreatePseudoDeclaration((ParserRuleContext) identifier, reference)
where !pseudoDeclaration.Annotations.Any()
select new MemberNotOnInterfaceInspectionResult(this, pseudoDeclaration, (ParserRuleContext) identifier, typeDeclaration))
.Cast<InspectionResultBase>().ToList();
}

//Builds a throw-away Declaration for the indentifiers found by the inspection. These aren't (and shouldn't be) created by the parser.
//Used to pass to the InspectionResult to make it selectable.
private static Declaration CreatePseudoDeclaration(ParserRuleContext context, IdentifierReference reference)
{
return new Declaration(
new QualifiedMemberName(reference.QualifiedModuleName, context.GetText()),
null,
null,
string.Empty,
string.Empty,
false,
false,
Accessibility.Implicit,
DeclarationType.Variable,
context,
context.GetSelection(),
false,
null,
true,
null,
null,
true);
return (from access in unresolved
let callingContext = targets.FirstOrDefault(usage => usage.Context.Equals(access.CallingContext))
where callingContext != null
select
new MemberNotOnInterfaceInspectionResult(this, access, callingContext.Declaration.AsTypeDeclaration))
.ToList();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using Rubberduck.Inspections.Abstract;
using Rubberduck.Inspections.Resources;
using Rubberduck.VBEditor;

namespace Rubberduck.Inspections.QuickFixes
{
public class ApplicationWorksheetFunctionQuickFix : QuickFixBase
{
private readonly string _memberName;

public ApplicationWorksheetFunctionQuickFix(QualifiedSelection selection, string memberName)
: base(null, selection, InspectionsUI.ApplicationWorksheetFunctionQuickFix)
{
_memberName = memberName;
}

public override bool CanFixInModule { get { return true; } }
public override bool CanFixInProject { get { return true; } }

public override void Fix()
{
var module = Selection.QualifiedName.Component.CodeModule;

var oldContent = module.GetLines(Selection.Selection);
var newCall = string.Format("WorksheetFunction.{0}", _memberName);
var start = Selection.Selection.StartColumn - 1;
//The member being called will always be a single token, so this will always be safe (it will be a single line).
var end = Selection.Selection.EndColumn - 1;
var newContent = oldContent.Substring(0, start) + newCall +
(oldContent.Length > end
? oldContent.Substring(end, oldContent.Length - end)
: string.Empty);

module.DeleteLines(Selection.Selection);
module.InsertLines(Selection.Selection.StartLine, newContent);
}
}
}
36 changes: 36 additions & 0 deletions RetailCoder.VBE/Inspections/Resources/InspectionsUI.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions RetailCoder.VBE/Inspections/Resources/InspectionsUI.resx
Original file line number Diff line number Diff line change
Expand Up @@ -634,4 +634,17 @@ If the parameter can be null, ignore this inspection result; passing a null valu
<data name="HostSpecificExpressionInspectionResultFormat" xml:space="preserve">
<value>Expression '{0}' cannot be validated at compile-time.</value>
</data>
<data name="ApplicationWorksheetFunctionInspectionMeta" xml:space="preserve">
<value>The Excel Application object does not implement the WorksheetFunction interface directly. All calls made to WorksheetFunction members are handled as late bound and errors in the called member will be returned wrapped in a Variant of VbVarType.vbError. This makes errors un-trappable with error handlers and adds a performance penalty in comparison to early bound calls. Consider calling Application.WorksheetFunction explicitly. Note: If this call generated errors in the past, those errors were ignored. If applying the quick fix, proper error handling should be in place.</value>
</data>
<data name="ApplicationWorksheetFunctionInspectionName" xml:space="preserve">
<value>Late bound WorksheetFunction call.</value>
</data>
<data name="ApplicationWorksheetFunctionInspectionResultFormat" xml:space="preserve">
<value>Use of late bound Application.{0} member.</value>
<comment>{0} Member name</comment>
</data>
<data name="ApplicationWorksheetFunctionQuickFix" xml:space="preserve">
<value>Use Application.WorksheetFunction explicitly.</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System.Collections.Generic;
using Rubberduck.Common;
using Rubberduck.Inspections.Abstract;
using Rubberduck.Inspections.QuickFixes;
using Rubberduck.Inspections.Resources;
using Rubberduck.VBEditor;

namespace Rubberduck.Inspections.Results
{
public class ApplicationWorksheetFunctionInspectionResult : InspectionResultBase
{
private readonly QualifiedSelection _qualifiedSelection;
private readonly string _memberName;
private IEnumerable<QuickFixBase> _quickFixes;

public ApplicationWorksheetFunctionInspectionResult(IInspection inspection, QualifiedSelection qualifiedSelection, string memberName)
: base(inspection, qualifiedSelection.QualifiedName)
{
_memberName = memberName;
_qualifiedSelection = qualifiedSelection;
}

public override QualifiedSelection QualifiedSelection
{
get { return _qualifiedSelection; }
}

public override IEnumerable<QuickFixBase> QuickFixes
{
get
{
return _quickFixes ?? (_quickFixes = new QuickFixBase[]
{
new IgnoreOnceQuickFix(null, _qualifiedSelection, Inspection.AnnotationName),
new ApplicationWorksheetFunctionQuickFix(_qualifiedSelection, _memberName)
});
}
}

public override string Description
{
get { return string.Format(InspectionsUI.ApplicationWorksheetFunctionInspectionResultFormat, _memberName).Captialize(); }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,12 @@ namespace Rubberduck.Inspections.Results
{
public class MemberNotOnInterfaceInspectionResult : InspectionResultBase
{
private readonly ParserRuleContext _member;
private readonly Declaration _asTypeDeclaration;
private IEnumerable<QuickFixBase> _quickFixes;

public MemberNotOnInterfaceInspectionResult(IInspection inspection, Declaration target, ParserRuleContext member, Declaration asTypeDeclaration)
public MemberNotOnInterfaceInspectionResult(IInspection inspection, Declaration target, Declaration asTypeDeclaration)
: base(inspection, target)
{
_member = member;
_asTypeDeclaration = asTypeDeclaration;
}

Expand All @@ -26,14 +24,14 @@ public override IEnumerable<QuickFixBase> QuickFixes
{
return _quickFixes ?? (_quickFixes = new QuickFixBase[]
{
new IgnoreOnceQuickFix(_member, QualifiedSelection, Inspection.AnnotationName)
new IgnoreOnceQuickFix(Target.Context, QualifiedSelection, Inspection.AnnotationName)
});
}
}

public override string Description
{
get { return string.Format(InspectionsUI.MemberNotOnInterfaceInspectionResultFormat, _member.GetText(), _asTypeDeclaration.IdentifierName); }
get { return string.Format(InspectionsUI.MemberNotOnInterfaceInspectionResultFormat, Target.IdentifierName, _asTypeDeclaration.IdentifierName); }
}
}
}
3 changes: 3 additions & 0 deletions RetailCoder.VBE/Rubberduck.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -365,17 +365,20 @@
<Compile Include="Common\WinAPI\WM.cs" />
<Compile Include="Common\WindowsOperatingSystem.cs" />
<Compile Include="Common\UndocumentedAttribute.cs" />
<Compile Include="Inspections\ApplicationWorksheetFunctionInspection.cs" />
<Compile Include="Inspections\HostSpecificExpressionInspection.cs" />
<Compile Include="Inspections\HungarianNotationInspection.cs" />
<Compile Include="Inspections\ImplicitDefaultMemberAssignmentInspection.cs" />
<Compile Include="Inspections\MemberNotOnInterfaceInspection.cs" />
<Compile Include="Inspections\QuickFixes\AddIdentifierToWhiteListQuickFix.cs" />
<Compile Include="Inspections\QuickFixes\ApplicationWorksheetFunctionQuickFix.cs" />
<Compile Include="Inspections\Resources\InspectionsUI.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>InspectionsUI.resx</DependentUpon>
</Compile>
<Compile Include="Inspections\Results\AggregateInspectionResult.cs" />
<Compile Include="Inspections\Results\ApplicationWorksheetFunctionInspectionResult.cs" />
<Compile Include="Inspections\Results\HostSpecificExpressionInspectionResult.cs" />
<Compile Include="Inspections\Results\ImplicitDefaultMemberAssignmentInspectionResult.cs" />
<Compile Include="Inspections\QuickFixes\IntroduceLocalVariableQuickFix.cs" />
Expand Down
5 changes: 2 additions & 3 deletions RetailCoder.VBE/UnitTesting/TestEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
using System.Diagnostics;
using System.Linq;
using Rubberduck.Parsing.Annotations;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.UI.UnitTesting;
using Rubberduck.VBEditor;
using Rubberduck.VBEditor.Application;
using Rubberduck.VBEditor.Extensions;
using Rubberduck.VBEditor.SafeComWrappers.Abstract;

namespace Rubberduck.UnitTesting
Expand Down Expand Up @@ -99,7 +98,7 @@ public void Run(IEnumerable<TestMethod> tests)
}
}

private void Run(IEnumerable<QualifiedMemberName> members)
private void Run(IEnumerable<Declaration> members)
{
if (_hostApplication == null)
{
Expand Down
2 changes: 1 addition & 1 deletion RetailCoder.VBE/UnitTesting/TestMethod.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public void Run()
try
{
AssertHandler.OnAssertCompleted += HandleAssertCompleted;
_hostApp.Run(Declaration.QualifiedName);
_hostApp.Run(Declaration);
AssertHandler.OnAssertCompleted -= HandleAssertCompleted;

result = EvaluateResults();
Expand Down
Loading