-
Notifications
You must be signed in to change notification settings - Fork 300
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #6238 from retailcoder/inspections-cleanup
Various inspection-related clean-ups, fixes, and enhancements
- Loading branch information
Showing
170 changed files
with
2,865 additions
and
1,831 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
63 changes: 63 additions & 0 deletions
63
Rubberduck.CodeAnalysis/Inspections/Abstract/InvalidAnnotationInspectionBase.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
using Rubberduck.CodeAnalysis.Inspections.Results; | ||
using Rubberduck.Parsing; | ||
using Rubberduck.Parsing.Annotations; | ||
using Rubberduck.Parsing.Symbols; | ||
using Rubberduck.Parsing.VBA; | ||
using Rubberduck.Parsing.VBA.DeclarationCaching; | ||
using Rubberduck.VBEditor; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
|
||
namespace Rubberduck.CodeAnalysis.Inspections.Abstract | ||
{ | ||
/// <summary> | ||
/// An inspection that flags invalid annotation comments. | ||
/// </summary> | ||
internal abstract class InvalidAnnotationInspectionBase : InspectionBase | ||
{ | ||
protected InvalidAnnotationInspectionBase(IDeclarationFinderProvider declarationFinderProvider) | ||
: base(declarationFinderProvider) { } | ||
|
||
protected QualifiedContext Context(IParseTreeAnnotation pta) => | ||
new QualifiedContext(pta.QualifiedSelection.QualifiedName, pta.Context); | ||
|
||
protected sealed override IEnumerable<IInspectionResult> DoGetInspectionResults(DeclarationFinder finder) | ||
{ | ||
return finder.UserDeclarations(DeclarationType.Module) | ||
.Where(module => module != null) | ||
.SelectMany(module => DoGetInspectionResults(module.QualifiedModuleName, finder)); | ||
} | ||
|
||
protected IInspectionResult InspectionResult(IParseTreeAnnotation pta) => | ||
new QualifiedContextInspectionResult(this, ResultDescription(pta), Context(pta)); | ||
|
||
/// <summary> | ||
/// Gets all invalid annotations covered by this inspection. | ||
/// </summary> | ||
/// <param name="annotations">All user code annotations.</param> | ||
/// <param name="userDeclarations">All user declarations.</param> | ||
/// <param name="identifierReferences">All identifier references in user code.</param> | ||
/// <returns></returns> | ||
protected abstract IEnumerable<IParseTreeAnnotation> GetInvalidAnnotations( | ||
IEnumerable<IParseTreeAnnotation> annotations, | ||
IEnumerable<Declaration> userDeclarations, | ||
IEnumerable<IdentifierReference> identifierReferences); | ||
|
||
/// <summary> | ||
/// Gets an annotation-specific description for an inspection result. | ||
/// </summary> | ||
/// <param name="pta">The invalid annotation.</param> | ||
/// <returns></returns> | ||
protected abstract string ResultDescription(IParseTreeAnnotation pta); | ||
|
||
protected sealed override IEnumerable<IInspectionResult> DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder) | ||
{ | ||
var annotations = finder.FindAnnotations(module); | ||
var userDeclarations = finder.Members(module).ToList(); | ||
var identifierReferences = finder.IdentifierReferences(module).ToList(); | ||
|
||
var invalidAnnotations = GetInvalidAnnotations(annotations, userDeclarations, identifierReferences); | ||
return invalidAnnotations.Select(InspectionResult).ToList(); | ||
} | ||
} | ||
} |
80 changes: 80 additions & 0 deletions
80
...duck.CodeAnalysis/Inspections/Concrete/AnnotationInIncompatibleComponentTypeInspection.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
using Rubberduck.CodeAnalysis.Inspections.Abstract; | ||
using Rubberduck.Parsing; | ||
using Rubberduck.Parsing.Annotations; | ||
using Rubberduck.Parsing.Symbols; | ||
using Rubberduck.Parsing.VBA; | ||
using Rubberduck.Resources.Inspections; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Linq; | ||
|
||
namespace Rubberduck.CodeAnalysis.Inspections.Concrete | ||
{ | ||
/// <summary> | ||
/// Flags Rubberduck annotations used in a component type that is incompatible with that annotation. | ||
/// </summary> | ||
/// <why> | ||
/// Some annotations can only be used in a specific type of module; others cannot be used in certain types of modules. | ||
/// </why> | ||
/// <example hasResult="true"> | ||
/// <module name="MyModule" type="Standard Module"> | ||
/// <![CDATA[ | ||
/// '@PredeclaredId 'this annotation is illegal in a standard module | ||
/// Option Explicit | ||
/// ]]> | ||
/// </module> | ||
/// </example> | ||
/// <example hasResult="false"> | ||
/// <module name="MyModule" type="Class Module"> | ||
/// <![CDATA[ | ||
/// '@PredeclaredId 'this annotation works fine in a class module | ||
/// Option Explicit | ||
/// | ||
/// Public Sub DoSomething() | ||
/// Dim foo As Long | ||
/// End Sub | ||
/// ]]> | ||
/// </module> | ||
/// </example> | ||
internal sealed class AnnotationInIncompatibleComponentTypeInspection : InvalidAnnotationInspectionBase | ||
{ | ||
public AnnotationInIncompatibleComponentTypeInspection(IDeclarationFinderProvider declarationFinderProvider) | ||
: base(declarationFinderProvider) { } | ||
|
||
protected override IEnumerable<IParseTreeAnnotation> GetInvalidAnnotations( | ||
IEnumerable<IParseTreeAnnotation> annotations, | ||
IEnumerable<Declaration> userDeclarations, | ||
IEnumerable<IdentifierReference> identifierReferences) | ||
{ | ||
foreach (var pta in annotations) | ||
{ | ||
var annotation = pta.Annotation; | ||
var componentType = pta.QualifiedSelection.QualifiedName.ComponentType; | ||
if (annotation.RequiredComponentType.HasValue && annotation.RequiredComponentType != componentType | ||
|| annotation.IncompatibleComponentTypes.Contains(componentType)) | ||
{ | ||
yield return pta; | ||
} | ||
} | ||
|
||
yield break; | ||
} | ||
|
||
protected override string ResultDescription(IParseTreeAnnotation pta) | ||
{ | ||
if (pta.Annotation.RequiredComponentType.HasValue) | ||
{ | ||
return string.Format(InspectionResults.ResourceManager.GetString($"{nameof(InvalidAnnotationInspection)}_NotInRequiredComponentType", CultureInfo.CurrentUICulture), | ||
pta.Annotation.Name, // annotation... | ||
pta.QualifiedSelection.QualifiedName.ComponentType, // is used in a... | ||
pta.Annotation.RequiredComponentType); // but is only valid in a... | ||
} | ||
else | ||
{ | ||
return string.Format(InspectionResults.ResourceManager.GetString($"{nameof(InvalidAnnotationInspection)}_IncompatibleComponentType", CultureInfo.CurrentUICulture), | ||
pta.Annotation.Name, // annotation... | ||
pta.QualifiedSelection.QualifiedName.ComponentType); // cannot be used in a... | ||
} | ||
} | ||
} | ||
} |
Oops, something went wrong.