Skip to content

Commit 963bac6

Browse files
committed
Merge branch 'next' into BetterMemberAnnotationScoping
2 parents 96d4b1b + 7733e38 commit 963bac6

File tree

110 files changed

+7530
-2454
lines changed

Some content is hidden

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

110 files changed

+7530
-2454
lines changed
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.Inspections.Abstract;
4+
using Rubberduck.Inspections.Results;
5+
using Rubberduck.Parsing;
6+
using Rubberduck.Parsing.Annotations;
7+
using Rubberduck.Parsing.Inspections;
8+
using Rubberduck.Parsing.Inspections.Abstract;
9+
using Rubberduck.Parsing.Symbols;
10+
using Rubberduck.Parsing.VBA;
11+
using Rubberduck.Resources.Inspections;
12+
13+
namespace Rubberduck.Inspections.Concrete
14+
{
15+
[CannotAnnotate]
16+
public sealed class AttributeValueOutOfSyncInspection : InspectionBase
17+
{
18+
public AttributeValueOutOfSyncInspection(RubberduckParserState state)
19+
:base(state)
20+
{
21+
}
22+
23+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
24+
{
25+
var declarationsWithAttributeAnnotations = State.DeclarationFinder.AllUserDeclarations
26+
.Where(declaration => declaration.Annotations.Any(annotation => annotation.AnnotationType.HasFlag(AnnotationType.Attribute)));
27+
var results = new List<DeclarationInspectionResult>();
28+
foreach (var declaration in declarationsWithAttributeAnnotations)
29+
{
30+
foreach (var annotation in declaration.Annotations.OfType<IAttributeAnnotation>())
31+
{
32+
if (HasDifferingAttributeValues(declaration, annotation, out var attributeValues))
33+
{
34+
var description = string.Format(InspectionResults.AttributeValueOutOfSyncInspection,
35+
annotation.Attribute,
36+
string.Join(", ", attributeValues),
37+
annotation.AnnotationType);
38+
39+
var result = new DeclarationInspectionResult(this, description, declaration,
40+
new QualifiedContext(declaration.QualifiedModuleName, annotation.Context));
41+
result.Properties.Annotation = annotation;
42+
result.Properties.AttributeValues = attributeValues;
43+
44+
results.Add(result);
45+
}
46+
}
47+
}
48+
49+
return results;
50+
}
51+
52+
private static bool HasDifferingAttributeValues(Declaration declaration, IAttributeAnnotation annotation, out IReadOnlyList<string> attributeValues)
53+
{
54+
var attributeNodes = declaration.DeclarationType.HasFlag(DeclarationType.Module)
55+
? declaration.Attributes.AttributeNodesFor(annotation)
56+
: declaration.Attributes.AttributeNodesFor(annotation, declaration.IdentifierName);
57+
58+
foreach (var attributeNode in attributeNodes)
59+
{
60+
var values = attributeNode.Values;
61+
if (!annotation.AttributeValues.SequenceEqual(values))
62+
{
63+
attributeValues = values;
64+
return true;
65+
}
66+
}
67+
attributeValues = new List<string>();
68+
return false;
69+
}
70+
}
71+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Rubberduck.Inspections.Abstract;
4+
using Rubberduck.Inspections.Concrete;
5+
using Rubberduck.Parsing.Annotations;
6+
using Rubberduck.Parsing.Inspections.Abstract;
7+
using Rubberduck.Parsing.Rewriter;
8+
using Rubberduck.Parsing.Symbols;
9+
using Rubberduck.Parsing.VBA;
10+
using Rubberduck.Parsing.VBA.Parsing;
11+
12+
namespace Rubberduck.Inspections.QuickFixes
13+
{
14+
public class AdjustAttributeValuesQuickFix : QuickFixBase
15+
{
16+
private readonly IAttributesUpdater _attributesUpdater;
17+
18+
public AdjustAttributeValuesQuickFix(IAttributesUpdater attributesUpdater)
19+
: base(typeof(AttributeValueOutOfSyncInspection))
20+
{
21+
_attributesUpdater = attributesUpdater;
22+
}
23+
24+
public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
25+
{
26+
var declaration = result.Target;
27+
IAttributeAnnotation annotation = result.Properties.Annotation;
28+
IReadOnlyList<string> attributeValues = result.Properties.AttributeValues;
29+
30+
var attributeName = declaration.DeclarationType.HasFlag(DeclarationType.Module)
31+
? annotation.Attribute
32+
: $"{declaration.IdentifierName}.{annotation.Attribute}";
33+
34+
_attributesUpdater.UpdateAttribute(rewriteSession, declaration, attributeName, annotation.AttributeValues, attributeValues);
35+
}
36+
37+
public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.AdjustAttributeValuesQuickFix;
38+
39+
public override CodeKind TargetCodeKind => CodeKind.AttributesCode;
40+
41+
public override bool CanFixInProcedure => true;
42+
public override bool CanFixInModule => true;
43+
public override bool CanFixInProject => true;
44+
}
45+
}
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.IO;
4+
using System.Runtime.CompilerServices;
5+
using System.Runtime.InteropServices;
6+
using System.Runtime.InteropServices.ComTypes;
7+
using Rubberduck.Parsing.ComReflection;
8+
using Rubberduck.VBEditor;
9+
using Rubberduck.VBEditor.SafeComWrappers;
10+
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
11+
using Rubberduck.VBEditor.Utility;
12+
13+
namespace Rubberduck.AddRemoveReferences
14+
{
15+
public class ReferenceModel : INotifyPropertyChanged
16+
{
17+
public event PropertyChangedEventHandler PropertyChanged;
18+
19+
private ReferenceModel()
20+
{
21+
_info = new Lazy<ReferenceInfo>(GenerateInfo);
22+
}
23+
24+
public ReferenceModel(ReferenceInfo info, ReferenceKind type, bool recent = false, bool pinned = false) : this()
25+
{
26+
Guid = info.Guid;
27+
Name = info.Name;
28+
Description = Name;
29+
FullPath = info.FullPath;
30+
Major = info.Major;
31+
Minor = info.Minor;
32+
IsRecent = recent;
33+
IsPinned = pinned;
34+
Type = type;
35+
}
36+
37+
public ReferenceModel(IVBProject project, int priority) : this()
38+
{
39+
Name = project.Name ?? string.Empty;
40+
Priority = priority;
41+
Guid = Guid.Empty;
42+
Description = project.Description ?? project.Name;
43+
FullPath = project.FileName ?? string.Empty;
44+
IsBuiltIn = false;
45+
Type = ReferenceKind.Project;
46+
}
47+
48+
public ReferenceModel(RegisteredLibraryInfo info) : this()
49+
{
50+
Name = info.Name ?? string.Empty;
51+
Guid = info.Guid;
52+
Description = string.IsNullOrEmpty(info.Description) ? Path.GetFileNameWithoutExtension(info.FullPath) : info.Description;
53+
Major = info.Major;
54+
Minor = info.Minor;
55+
FullPath = info.FullPath;
56+
LocaleName = info.LocaleName;
57+
IsBuiltIn = false;
58+
Type = ReferenceKind.TypeLibrary;
59+
Flags = (TypeLibTypeFlags)info.Flags;
60+
IsRegistered = true;
61+
}
62+
63+
public ReferenceModel(RegisteredLibraryInfo info, IReference reference, int priority) : this(info)
64+
{
65+
Priority = priority;
66+
IsBuiltIn = reference.IsBuiltIn;
67+
IsBroken = reference.IsBroken;
68+
IsReferenced = true;
69+
}
70+
71+
public ReferenceModel(IReference reference, int priority) : this()
72+
{
73+
Priority = priority;
74+
Name = reference.Name;
75+
Guid = Guid.TryParse(reference.Guid, out var guid) ? guid : Guid.Empty;
76+
Description = string.IsNullOrEmpty(reference.Description) ? Path.GetFileNameWithoutExtension(reference.FullPath) : reference.Description;
77+
Major = reference.Major;
78+
Minor = reference.Minor;
79+
FullPath = reference.FullPath;
80+
IsBuiltIn = reference.IsBuiltIn;
81+
IsBroken = reference.IsBroken;
82+
IsReferenced = true;
83+
Type = reference.Type;
84+
}
85+
86+
public ReferenceModel(string path, ITypeLib reference, IComLibraryProvider provider) : this()
87+
{
88+
FullPath = path;
89+
90+
var documentation = provider.GetComDocumentation(reference);
91+
Name = documentation.Name;
92+
Description = documentation.DocString;
93+
94+
var info = provider.GetReferenceInfo(reference, Name, path);
95+
Guid = info.Guid;
96+
Major = info.Major;
97+
Minor = info.Minor;
98+
}
99+
100+
public ReferenceModel(string path, bool broken = false) : this()
101+
{
102+
FullPath = path;
103+
try
104+
{
105+
Name = Path.GetFileName(path) ?? path;
106+
Description = Name;
107+
}
108+
catch
109+
{
110+
// Yeah, that's probably busted.
111+
IsBroken = true;
112+
return;
113+
}
114+
115+
IsBroken = broken;
116+
}
117+
118+
private bool _pinned;
119+
public bool IsPinned
120+
{
121+
get => _pinned;
122+
set
123+
{
124+
_pinned = value;
125+
NotifyPropertyChanged();
126+
}
127+
}
128+
129+
public bool IsRecent { get; set; }
130+
public bool IsRegistered { get; set; }
131+
public bool IsReferenced { get; set; }
132+
133+
public int? Priority { get; set; }
134+
135+
public string Name { get; } = string.Empty;
136+
public Guid Guid { get; }
137+
public string Description { get; } = string.Empty;
138+
public string FullPath { get; }
139+
public string LocaleName { get; } = string.Empty;
140+
141+
public bool IsBuiltIn { get; set; }
142+
public bool IsBroken { get; }
143+
public TypeLibTypeFlags Flags { get; set; }
144+
public ReferenceKind Type { get; }
145+
146+
private string FullPath32 { get; } = string.Empty;
147+
private string FullPath64 { get; } = string.Empty;
148+
public int Major { get; set; }
149+
public int Minor { get; set; }
150+
public string Version => $"{Major}.{Minor}";
151+
152+
public ReferenceStatus Status
153+
{
154+
get
155+
{
156+
var status = IsPinned ? ReferenceStatus.Pinned : ReferenceStatus.None;
157+
if (!Priority.HasValue)
158+
{
159+
return IsRecent ? status | ReferenceStatus.Recent : status;
160+
}
161+
162+
if (IsBroken)
163+
{
164+
return status | ReferenceStatus.Broken;
165+
}
166+
167+
if (IsBuiltIn)
168+
{
169+
return status | ReferenceStatus.BuiltIn;
170+
}
171+
172+
return status | (IsReferenced ? ReferenceStatus.Loaded : ReferenceStatus.Added);
173+
}
174+
}
175+
176+
private readonly Lazy<ReferenceInfo> _info;
177+
private ReferenceInfo GenerateInfo() => new ReferenceInfo(Guid, Name, FullPath, Major, Minor);
178+
public ReferenceInfo ToReferenceInfo() => _info.Value;
179+
180+
public bool Matches(ReferenceInfo info)
181+
{
182+
return Major == info.Major && Minor == info.Minor &&
183+
FullPath.Equals(info.FullPath, StringComparison.OrdinalIgnoreCase) ||
184+
FullPath32.Equals(info.FullPath, StringComparison.OrdinalIgnoreCase) ||
185+
FullPath64.Equals(info.FullPath, StringComparison.OrdinalIgnoreCase) ||
186+
Guid.Equals(info.Guid);
187+
}
188+
189+
private void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
190+
{
191+
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
192+
}
193+
}
194+
}

0 commit comments

Comments
 (0)