Skip to content

Commit 7ceeb29

Browse files
committed
Fixed treatment of module scoped attributes, i.e. module attributes and module variable attributes.
1 parent 613cd78 commit 7ceeb29

File tree

4 files changed

+95
-76
lines changed

4 files changed

+95
-76
lines changed

Rubberduck.Parsing/Symbols/DeclarationSymbolsListener.cs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,14 +222,8 @@ private Declaration CreateDeclaration(
222222
else
223223
{
224224
var key = (identifierName, declarationType);
225-
if (!_attributes.TryGetValue(key, out var attributes))
226-
{
227-
attributes = null;
228-
}
229-
if (!_membersAllowingAttributes.TryGetValue(key, out var attributesPassContext))
230-
{
231-
attributesPassContext = null;
232-
}
225+
_attributes.TryGetValue(key, out var attributes);
226+
_membersAllowingAttributes.TryGetValue(key, out var attributesPassContext);
233227

234228
var annotations = FindAnnotations(selection.StartLine);
235229
switch (declarationType)

Rubberduck.Parsing/VBA/Attributes.cs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ public enum Instancing
2222
public class AttributeNode : IEquatable<AttributeNode>
2323
{
2424
private readonly IList<string> _values;
25+
private readonly HashSet<VBAParser.AttributeStmtContext> _contexts = new HashSet<VBAParser.AttributeStmtContext>();
2526

2627
public AttributeNode(VBAParser.AttributeStmtContext context)
2728
{
28-
Context = context;
29-
Name = Context?.attributeName().GetText() ?? String.Empty;
30-
_values = Context?.attributeValue().Select(a => a.GetText()).ToList() ?? new List<string>();
29+
_contexts.Add(context);
30+
Name = context?.attributeName().GetText() ?? string.Empty;
31+
_values = context?.attributeValue().Select(a => a.GetText()).ToList() ?? new List<string>();
3132
}
3233

3334
public AttributeNode(string name, IEnumerable<string> values)
@@ -36,7 +37,7 @@ public AttributeNode(string name, IEnumerable<string> values)
3637
_values = values.ToList();
3738
}
3839

39-
public VBAParser.AttributeStmtContext Context { get; }
40+
public IReadOnlyCollection<VBAParser.AttributeStmtContext> Contexts => _contexts;
4041

4142
public string Name { get; }
4243

@@ -45,6 +46,21 @@ public void AddValue(string value)
4546
_values.Add(value);
4647
}
4748

49+
public void AddContext(VBAParser.AttributeStmtContext context)
50+
{
51+
if (context == null || !Name.Equals(context.attributeName().GetText(), StringComparison.OrdinalIgnoreCase))
52+
{
53+
return;
54+
}
55+
56+
_contexts.Add(context);
57+
var values = context.attributeValue().Select(e => e.GetText().Replace("\"", string.Empty)).ToList();
58+
foreach (var value in values.Where(v => !HasValue(v)))
59+
{
60+
AddValue(value);
61+
}
62+
}
63+
4864
public IReadOnlyCollection<string> Values => _values.AsReadOnly();
4965

5066
public bool HasValue(string value)

Rubberduck.Parsing/VBA/DeclarationResolving/DeclarationResolveRunnerBase.cs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public abstract class DeclarationResolveRunnerBase : IDeclarationResolveRunner
2121
protected readonly IParserStateManager _parserStateManager;
2222
private readonly IProjectReferencesProvider _projectReferencesProvider;
2323

24-
public DeclarationResolveRunnerBase(
24+
protected DeclarationResolveRunnerBase(
2525
RubberduckParserState state,
2626
IParserStateManager parserStateManager,
2727
IProjectReferencesProvider projectReferencesProvider)
@@ -75,22 +75,23 @@ protected void ResolveDeclarations(QualifiedModuleName module, IParseTree tree,
7575

7676
private Declaration GetOrCreateProjectDeclaration(QualifiedModuleName module)
7777
{
78-
Declaration projectDeclaration;
79-
if (!_projectDeclarations.TryGetValue(module.ProjectId, out projectDeclaration))
78+
if (_projectDeclarations.TryGetValue(module.ProjectId, out var projectDeclaration))
8079
{
81-
var project = _state.ProjectsProvider.Project(module.ProjectId);
82-
projectDeclaration = CreateProjectDeclaration(project);
80+
return projectDeclaration;
8381

84-
if (projectDeclaration.ProjectId != module.ProjectId)
85-
{
86-
Logger.Error($"Inconsistent projectId between QualifiedModuleName {module} (projectID {module.ProjectId}) and its project (projectId {projectDeclaration.ProjectId})");
87-
throw new ArgumentException($"Inconsistent projectID on {nameof(module)}");
88-
}
82+
}
83+
var project = _state.ProjectsProvider.Project(module.ProjectId);
84+
projectDeclaration = CreateProjectDeclaration(project);
8985

90-
_projectDeclarations.AddOrUpdate(module.ProjectId, projectDeclaration, (s, c) => projectDeclaration);
91-
_state.AddDeclaration(projectDeclaration);
86+
if (projectDeclaration.ProjectId != module.ProjectId)
87+
{
88+
Logger.Error($"Inconsistent projectId between QualifiedModuleName {module} (projectID {module.ProjectId}) and its project (projectId {projectDeclaration.ProjectId})");
89+
throw new ArgumentException($"Inconsistent projectID on {nameof(module)}");
9290
}
9391

92+
_projectDeclarations.AddOrUpdate(module.ProjectId, projectDeclaration, (s, c) => projectDeclaration);
93+
_state.AddDeclaration(projectDeclaration);
94+
9495
return projectDeclaration;
9596
}
9697

Rubberduck.Parsing/VBA/Parsing/AttributeListener.cs

Lines changed: 60 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -14,88 +14,64 @@ public class AttributeListener : VBAParserBaseListener
1414
private readonly Dictionary<(string scopeIdentifier, DeclarationType scopeType), ParserRuleContext> _membersAllowingAttributes
1515
= new Dictionary<(string scopeIdentifier, DeclarationType scopeType), ParserRuleContext>();
1616

17-
private readonly (string scopeIdentifier, DeclarationType scopeType) _initialScope;
17+
private readonly (string scopeIdentifier, DeclarationType scopeType) _moduleScope;
1818
private (string scopeIdentifier, DeclarationType scopeType) _currentScope;
19-
private IAnnotatedContext _currentAnnotatedContext;
2019
private Attributes _currentScopeAttributes;
2120

22-
public AttributeListener((string scopeIdentifier, DeclarationType scopeType) initialScope)
21+
public AttributeListener((string scopeIdentifier, DeclarationType scopeType) moduleScope)
2322
{
24-
_initialScope = initialScope;
25-
_currentScope = initialScope;
26-
_currentScopeAttributes = new Attributes();
23+
_moduleScope = moduleScope;
24+
_currentScope = moduleScope;
2725
}
2826

2927
public IDictionary<(string scopeIdentifier, DeclarationType scopeType), Attributes> Attributes => _attributes;
3028
public IDictionary<(string scopeIdentifier, DeclarationType scopeType), ParserRuleContext> MembersAllowingAttributes => _membersAllowingAttributes;
3129

32-
public override void ExitAnnotation(VBAParser.AnnotationContext context)
30+
public override void EnterStartRule(VBAParser.StartRuleContext context)
3331
{
34-
_currentAnnotatedContext?.Annotate(context);
35-
context.AnnotatedContext = _currentAnnotatedContext as ParserRuleContext;
32+
_membersAllowingAttributes[_moduleScope] = context;
3633
}
3734

38-
public override void ExitModuleAttributes(VBAParser.ModuleAttributesContext context)
35+
public override void EnterModuleVariableStmt(VBAParser.ModuleVariableStmtContext context)
3936
{
40-
if(_currentScopeAttributes.Any() && !_attributes.ContainsKey(_currentScope))
37+
var variableDeclarationStatemenList = context.variableStmt().variableListStmt().variableSubStmt();
38+
foreach (var variableContext in variableDeclarationStatemenList)
4139
{
42-
_attributes.Add(_currentScope, _currentScopeAttributes);
40+
var variableName = Identifier.GetName(variableContext);
41+
_membersAllowingAttributes[(variableName, DeclarationType.Variable)] = context;
4342
}
4443
}
4544

46-
public override void EnterModuleVariableStmt(VBAParser.ModuleVariableStmtContext context)
45+
public override void EnterSubStmt(VBAParser.SubStmtContext context)
4746
{
4847
_currentScopeAttributes = new Attributes();
49-
var annotatedContext = context.variableStmt().variableListStmt().variableSubStmt().Last();
50-
_currentScope = (Identifier.GetName(annotatedContext), DeclarationType.Variable);
51-
_currentAnnotatedContext = annotatedContext;
48+
_currentScope = (Identifier.GetName(context.subroutineName()), DeclarationType.Procedure);
5249
_membersAllowingAttributes[_currentScope] = context;
5350
}
5451

55-
public override void ExitModuleVariableStmt(VBAParser.ModuleVariableStmtContext context)
52+
public override void ExitSubStmt(VBAParser.SubStmtContext context)
5653
{
57-
if (_currentScopeAttributes.Any())
54+
if(_currentScopeAttributes.Any())
5855
{
5956
_attributes.Add(_currentScope, _currentScopeAttributes);
60-
var annotatedContext = context.variableStmt().variableListStmt().variableSubStmt().Last();
61-
annotatedContext.AddAttributes(_currentScopeAttributes);
57+
context.AddAttributes(_currentScopeAttributes);
6258
}
6359

6460
ResetScope();
6561
}
6662

6763
private void ResetScope()
6864
{
69-
_currentScope = _initialScope;
65+
_currentScope = _moduleScope;
7066
_currentScopeAttributes = _attributes.TryGetValue(_currentScope, out var attributes)
7167
? attributes
7268
: new Attributes();
7369
}
7470

75-
public override void EnterSubStmt(VBAParser.SubStmtContext context)
76-
{
77-
_currentScopeAttributes = new Attributes();
78-
_currentScope = (Identifier.GetName(context.subroutineName()), DeclarationType.Procedure);
79-
_currentAnnotatedContext = context;
80-
_membersAllowingAttributes[_currentScope] = context;
81-
}
82-
83-
public override void ExitSubStmt(VBAParser.SubStmtContext context)
84-
{
85-
if(_currentScopeAttributes.Any())
86-
{
87-
_attributes.Add(_currentScope, _currentScopeAttributes);
88-
context.AddAttributes(_currentScopeAttributes);
89-
}
90-
91-
ResetScope();
92-
}
93-
9471
public override void EnterFunctionStmt(VBAParser.FunctionStmtContext context)
9572
{
9673
_currentScopeAttributes = new Attributes();
9774
_currentScope = (Identifier.GetName(context.functionName()), DeclarationType.Function);
98-
_currentAnnotatedContext = context;
9975
_membersAllowingAttributes[_currentScope] = context;
10076
}
10177

@@ -114,7 +90,6 @@ public override void EnterPropertyGetStmt(VBAParser.PropertyGetStmtContext conte
11490
{
11591
_currentScopeAttributes = new Attributes();
11692
_currentScope = (Identifier.GetName(context.functionName()), DeclarationType.PropertyGet);
117-
_currentAnnotatedContext = context;
11893
_membersAllowingAttributes[_currentScope] = context;
11994
}
12095

@@ -133,7 +108,6 @@ public override void EnterPropertyLetStmt(VBAParser.PropertyLetStmtContext conte
133108
{
134109
_currentScopeAttributes = new Attributes();
135110
_currentScope = (Identifier.GetName(context.subroutineName()), DeclarationType.PropertyLet);
136-
_currentAnnotatedContext = context;
137111
_membersAllowingAttributes[_currentScope] = context;
138112
}
139113

@@ -152,7 +126,6 @@ public override void EnterPropertySetStmt(VBAParser.PropertySetStmtContext conte
152126
{
153127
_currentScopeAttributes = new Attributes();
154128
_currentScope = (Identifier.GetName(context.subroutineName()), DeclarationType.PropertySet);
155-
_currentAnnotatedContext = context;
156129
_membersAllowingAttributes[_currentScope] = context;
157130
}
158131

@@ -169,19 +142,54 @@ public override void ExitPropertySetStmt(VBAParser.PropertySetStmtContext contex
169142

170143
public override void ExitAttributeStmt(VBAParser.AttributeStmtContext context)
171144
{
172-
var values = context.attributeValue().Select(e => e.GetText().Replace("\"", string.Empty)).ToList();
145+
var attributeName = context.attributeName().GetText();
146+
var attributeNameParts = attributeName.Split('.');
147+
148+
//Module attribute
149+
if (attributeNameParts.Length == 1)
150+
{
151+
AddOrUpdateAttribute(_moduleScope, attributeName, context);
152+
return;
153+
}
154+
155+
var scopeName = attributeNameParts[0];
156+
157+
if (scopeName.Equals(_currentScope.scopeIdentifier, StringComparison.OrdinalIgnoreCase))
158+
{
159+
AddOrUpdateAttribute(_currentScopeAttributes, attributeName, context);
160+
return;
161+
}
162+
163+
//Member variable attributes
164+
var moduleVariableScope = (scopeName, DeclarationType.Variable);
165+
if (_membersAllowingAttributes.TryGetValue(moduleVariableScope, out _))
166+
{
167+
AddOrUpdateAttribute(moduleVariableScope, attributeName, context);
168+
}
169+
}
170+
171+
private void AddOrUpdateAttribute((string scopeName, DeclarationType Variable) moduleVariableScope,
172+
string attributeName, VBAParser.AttributeStmtContext context)
173+
{
174+
if (!_attributes.TryGetValue(moduleVariableScope, out var attributes))
175+
{
176+
attributes = new Attributes();
177+
_attributes.Add(moduleVariableScope, attributes);
178+
}
173179

174-
var attribute = _currentScopeAttributes
175-
.SingleOrDefault(a => a.Name.Equals(context.attributeName().GetText(), StringComparison.OrdinalIgnoreCase));
180+
AddOrUpdateAttribute(attributes, attributeName, context);
181+
}
182+
183+
private static void AddOrUpdateAttribute(Attributes attributes, string attributeName, VBAParser.AttributeStmtContext context)
184+
{
185+
var attribute = attributes.SingleOrDefault(a => a.Name.Equals(attributeName, StringComparison.OrdinalIgnoreCase));
176186
if (attribute != null)
177187
{
178-
foreach(var value in values.Where(v => !attribute.HasValue(v)))
179-
{
180-
attribute.AddValue(value);
181-
}
188+
attribute.AddContext(context);
189+
return;
182190
}
183191

184-
_currentScopeAttributes.Add(new AttributeNode(context));
192+
attributes.Add(new AttributeNode(context));
185193
}
186194
}
187195
}

0 commit comments

Comments
 (0)