Skip to content

Commit 95a16a8

Browse files
committed
2 parents 97cbd37 + e190a23 commit 95a16a8

File tree

10 files changed

+96
-53
lines changed

10 files changed

+96
-53
lines changed

RetailCoder.VBE/Inspections/UnassignedVariableUsageInspection.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public override IEnumerable<InspectionResultBase> GetInspectionResults()
3131
var lenbFunction = BuiltInDeclarations.SingleOrDefault(s => s.Scope == "VBE7.DLL;VBA.Strings.LenB");
3232

3333
return from issue in declarations
34-
where !DeclarationReferencesContainsReference(lenFunction, issue)
34+
where issue.References.Any()
35+
&& !DeclarationReferencesContainsReference(lenFunction, issue)
3536
&& !DeclarationReferencesContainsReference(lenbFunction, issue)
3637
select new UnassignedVariableUsageInspectionResult(this, issue.Context, issue.QualifiedName.QualifiedModuleName, issue);
3738
}

RetailCoder.VBE/Root/RubberduckModule.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,7 @@ private void ApplyConfigurationConvention(IEnumerable<Assembly> assemblies)
187187
.BindAllInterfaces()
188188
.Configure(binding => binding.InSingletonScope()));
189189

190-
Bind<IPersistable<SerializableDeclaration>>().To<XmlPersistableDeclarations>().InCallScope();
190+
Bind<IPersistable<SerializableDeclarationTree>>().To<XmlPersistableDeclarations>().InCallScope();
191191

192192
Bind<IPersistanceService<CodeInspectionSettings>>().To<XmlPersistanceService<CodeInspectionSettings>>().InCallScope();
193193
Bind<IPersistanceService<GeneralSettings>>().To<XmlPersistanceService<GeneralSettings>>().InCallScope();
@@ -412,9 +412,9 @@ private IEnumerable<ICommandMenuItem> GetRubberduckCommandBarItems()
412412
KernelInstance.Get<ReparseCommandMenuItem>(),
413413
KernelInstance.Get<ShowParserErrorsCommandMenuItem>(),
414414
KernelInstance.Get<ContextSelectionLabelMenuItem>(),
415-
//#if DEBUG
416-
// KernelInstance.Get<SerializeDeclarationsCommandMenuItem>()
417-
//#endif
415+
#if DEBUG
416+
KernelInstance.Get<SerializeDeclarationsCommandMenuItem>()
417+
#endif
418418
};
419419
}
420420

RetailCoder.VBE/Rubberduck.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@
279279
<Reference Include="System.Data" />
280280
<Reference Include="System.Drawing" />
281281
<Reference Include="System.Printing" />
282+
<Reference Include="System.Runtime.Serialization" />
282283
<Reference Include="System.Windows.Forms" />
283284
<Reference Include="System.Windows.Interactivity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
284285
<Reference Include="System.Xaml" />

RetailCoder.VBE/UI/Command/MenuItems/CommandBars/SerializeDeclarationsCommandMenuItem.cs

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.IO;
44
using System.Linq;
55
using System.Printing;
6+
using System.Runtime.Serialization;
67
using System.Text;
78
using System.Xml;
89
using System.Xml.Serialization;
@@ -26,9 +27,9 @@ public SerializeDeclarationsCommandMenuItem(CommandBase command) : base(command)
2627
public class SerializeDeclarationsCommand : CommandBase
2728
{
2829
private readonly RubberduckParserState _state;
29-
private readonly IPersistable<SerializableDeclaration> _service;
30+
private readonly IPersistable<SerializableDeclarationTree> _service;
3031

31-
public SerializeDeclarationsCommand(RubberduckParserState state, IPersistable<SerializableDeclaration> service)
32+
public SerializeDeclarationsCommand(RubberduckParserState state, IPersistable<SerializableDeclarationTree> service)
3233
: base(LogManager.GetCurrentClassLogger())
3334
{
3435
_state = state;
@@ -48,38 +49,41 @@ protected override void ExecuteImpl(object parameter)
4849
var path = Path.Combine(BasePath, "declarations");
4950
if (!Directory.Exists(path)) { Directory.CreateDirectory(path); }
5051

51-
var declarations = _state.AllDeclarations
52-
.Where(declaration => declaration.IsBuiltIn)
53-
.Select(declaration => new SerializableDeclaration(declaration))
54-
.GroupBy(declaration => declaration.QualifiedMemberName.QualifiedModuleName.ProjectPath);
55-
foreach (var project in declarations)
52+
foreach (var tree in _state.BuiltInDeclarationTrees)
5653
{
5754
System.Diagnostics.Debug.Assert(path != null, "project path isn't supposed to be null");
5855

59-
var filename = Path.GetFileNameWithoutExtension(project.Key) + ".xml";
60-
_service.Persist(Path.Combine(path, filename), project);
56+
var filename = Path.GetFileNameWithoutExtension(tree.Node.QualifiedMemberName.QualifiedModuleName.ProjectName) + ".xml";
57+
_service.Persist(Path.Combine(path, filename), tree);
6158
}
6259
}
6360
}
6461

65-
public class XmlPersistableDeclarations : IPersistable<SerializableDeclaration>
62+
public class XmlPersistableDeclarations : IPersistable<SerializableDeclarationTree>
6663
{
67-
public void Persist(string path, IEnumerable<SerializableDeclaration> items)
64+
public void Persist(string path, SerializableDeclarationTree tree)
6865
{
6966
if (string.IsNullOrEmpty(path)) { throw new InvalidOperationException(); }
7067

71-
var emptyNamespace = new XmlSerializerNamespaces(new[] { XmlQualifiedName.Empty });
72-
using (var writer = new StreamWriter(path, false))
68+
var xmlSettings = new XmlWriterSettings
7369
{
74-
var serializer = new XmlSerializer(typeof(SerializableDeclaration));
75-
foreach (var item in items)
76-
{
77-
serializer.Serialize(writer, item, emptyNamespace);
78-
}
70+
NamespaceHandling = NamespaceHandling.OmitDuplicates,
71+
Encoding = Encoding.UTF8,
72+
//Indent = true
73+
};
74+
75+
using (var stream = new FileStream(path, FileMode.Create, FileAccess.Write))
76+
using (var xmlWriter = XmlWriter.Create(stream, xmlSettings))
77+
using (var writer = XmlDictionaryWriter.CreateDictionaryWriter(xmlWriter))
78+
{
79+
writer.WriteStartDocument();
80+
var settings = new DataContractSerializerSettings {RootNamespace = XmlDictionaryString.Empty};
81+
var serializer = new DataContractSerializer(typeof (SerializableDeclarationTree), settings);
82+
serializer.WriteObject(writer, tree);
7983
}
8084
}
8185

82-
public IEnumerable<SerializableDeclaration> Load(string path)
86+
public SerializableDeclarationTree Load(string path)
8387
{
8488
if (string.IsNullOrEmpty(path)) { throw new InvalidOperationException(); }
8589
throw new NotImplementedException();

Rubberduck.Parsing/Symbols/ReferencedDeclarationsCollector.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ public List<Declaration> GetDeclarationsForReference(IReference reference, out S
303303
return output;
304304
}
305305

306+
[Obsolete("Use the overload that outputs a SerializableDeclarationTree instead.")]
306307
public List<Declaration> GetDeclarationsForReference(IReference reference)
307308
{
308309
SerializableDeclarationTree tree;

Rubberduck.Parsing/Symbols/SerializableDeclaration.cs

Lines changed: 24 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ namespace Rubberduck.Parsing.Symbols
1010
[DataContract]
1111
public class SerializableDeclarationTree
1212
{
13-
private readonly SerializableDeclaration _node;
14-
private readonly IEnumerable<SerializableDeclarationTree> _children;
13+
[DataMember(IsRequired = true)]
14+
public readonly SerializableDeclaration Node;
15+
16+
[DataMember(IsRequired = true)]
17+
public readonly IEnumerable<SerializableDeclarationTree> Children;
1518

1619
public SerializableDeclarationTree(Declaration declaration)
1720
: this(new SerializableDeclaration(declaration)) { }
@@ -21,15 +24,9 @@ public SerializableDeclarationTree(SerializableDeclaration node)
2124

2225
public SerializableDeclarationTree(SerializableDeclaration node, IEnumerable<SerializableDeclarationTree> children)
2326
{
24-
_node = node;
25-
_children = children;
27+
Node = node;
28+
Children = children;
2629
}
27-
28-
[DataMember]
29-
public SerializableDeclaration Node { get { return _node; } }
30-
31-
[DataMember]
32-
public IEnumerable<SerializableDeclarationTree> Children { get { return _children; } }
3330
}
3431

3532
public class SerializableDeclaration
@@ -41,10 +38,11 @@ public SerializableDeclaration(Declaration declaration)
4138
{
4239
IdentifierName = declaration.IdentifierName;
4340

41+
//todo: figure these out
42+
//Annotations = declaration.Annotations.Cast<AnnotationBase>().ToArray();
43+
//Attributes = declaration.Attributes.ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToArray());
44+
4445
ParentScope = declaration.ParentScope;
45-
QualifiedMemberName = declaration.QualifiedName;
46-
Annotations = declaration.Annotations.Cast<AnnotationBase>().ToArray();
47-
Attributes = declaration.Attributes.ToArray();
4846
TypeHint = declaration.TypeHint;
4947
AsTypeName = declaration.AsTypeName;
5048
IsArray = declaration.IsArray;
@@ -53,13 +51,22 @@ public SerializableDeclaration(Declaration declaration)
5351
IsWithEvents = declaration.IsWithEvents;
5452
Accessibility = declaration.Accessibility;
5553
DeclarationType = declaration.DeclarationType;
54+
55+
MemberName = declaration.QualifiedName.MemberName;
56+
ProjectName = declaration.QualifiedName.QualifiedModuleName.ProjectName;
57+
ProjectPath = declaration.QualifiedName.QualifiedModuleName.ProjectPath;
58+
ComponentName = declaration.QualifiedName.QualifiedModuleName.ComponentName;
5659
}
5760

5861
public string IdentifierName { get; set; }
5962

60-
public QualifiedMemberName QualifiedMemberName { get; set; }
61-
public AnnotationBase[] Annotations { get; set; }
62-
public KeyValuePair<string, IEnumerable<string>>[] Attributes { get; set; }
63+
public string MemberName { get; set; }
64+
public string ProjectName { get; set; }
65+
public string ProjectPath { get; set; }
66+
public string ComponentName { get; set; }
67+
68+
public QualifiedModuleName QualifiedModuleName { get { return new QualifiedModuleName(ProjectName, ProjectPath, ComponentName); } }
69+
public QualifiedMemberName QualifiedMemberName { get { return new QualifiedMemberName(QualifiedModuleName, MemberName); } }
6370

6471
public string ParentScope { get; set; }
6572
public string AsTypeName { get; set; }
@@ -73,12 +80,7 @@ public SerializableDeclaration(Declaration declaration)
7380

7481
public Declaration Unwrap(Declaration parent)
7582
{
76-
var attributes = new Attributes();
77-
foreach (var keyValuePair in Attributes)
78-
{
79-
attributes.Add(keyValuePair.Key, keyValuePair.Value);
80-
}
81-
return new Declaration(QualifiedMemberName, parent, ParentScope, AsTypeName, TypeHint, IsSelfAssigned, IsWithEvents, Accessibility, DeclarationType, null, Selection.Empty, IsArray, null, IsBuiltIn, Annotations, attributes);
83+
return new Declaration(QualifiedMemberName, parent, ParentScope, AsTypeName, TypeHint, IsSelfAssigned, IsWithEvents, Accessibility, DeclarationType, null, Selection.Empty, IsArray, null, IsBuiltIn);
8284
}
8385
}
8486
}

Rubberduck.Parsing/VBA/RubberduckParser.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,12 @@ private void SyncComReferences(IReadOnlyList<IVBProject> projects)
433433
try
434434
{
435435
var comReflector = new ReferencedDeclarationsCollector(State);
436-
var items = comReflector.GetDeclarationsForReference(localReference);
436+
SerializableDeclarationTree tree;
437+
var items = comReflector.GetDeclarationsForReference(localReference, out tree);
438+
if (tree != null)
439+
{
440+
State.BuiltInDeclarationTrees.Add(tree);
441+
}
437442

438443
foreach (var declaration in items)
439444
{

Rubberduck.Parsing/VBA/RubberduckParserState.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,9 @@ public IReadOnlyList<Declaration> AllDeclarations
585585
}
586586
}
587587

588+
private readonly List<SerializableDeclarationTree> _builtInDeclarationTrees = new List<SerializableDeclarationTree>();
589+
public IList<SerializableDeclarationTree> BuiltInDeclarationTrees { get { return _builtInDeclarationTrees; } }
590+
588591
/// <summary>
589592
/// Gets a copy of the collected declarations, excluding the built-in ones.
590593
/// </summary>
Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
using System.Collections.Generic;
2-
3-
namespace Rubberduck.SettingsProvider
1+
namespace Rubberduck.SettingsProvider
42
{
5-
public interface IPersistable<T> where T : new()
3+
public interface IPersistable<T> where T : class
64
{
7-
void Persist(string path, IEnumerable<T> items);
8-
IEnumerable<T> Load(string path);
5+
void Persist(string path, T tree);
6+
T Load(string path);
97
}
108
}

RubberduckTests/Inspections/UnassignedVariableUsageInspectionTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,34 @@ Dim bb As Boolean
155155
Assert.IsFalse(inspectionResults.Any());
156156
}
157157

158+
[TestMethod]
159+
public void UnassignedVariableUsage_NoResultIfNoReferences()
160+
{
161+
const string inputCode =
162+
@"Sub DoSomething()
163+
Dim foo
164+
End Sub";
165+
166+
//Arrange
167+
var builder = new MockVbeBuilder();
168+
var project = builder.ProjectBuilder("VBAProject", ProjectProtection.Unprotected)
169+
.AddComponent("MyClass", ComponentType.ClassModule, inputCode)
170+
.Build();
171+
var vbe = builder.AddProject(project).Build();
172+
173+
var mockHost = new Mock<IHostApplication>();
174+
mockHost.SetupAllProperties();
175+
var parser = MockParser.Create(vbe.Object, new RubberduckParserState(new Mock<ISinks>().Object));
176+
177+
parser.Parse(new CancellationTokenSource());
178+
if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
179+
180+
var inspection = new UnassignedVariableUsageInspection(parser.State);
181+
var inspectionResults = inspection.GetInspectionResults();
182+
183+
Assert.IsFalse(inspectionResults.Any());
184+
}
185+
158186
// Ignored until we can reinstate the quick fix on a specific reference
159187
// [TestMethod]
160188
// [TestCategory("Inspections")]

0 commit comments

Comments
 (0)