3
3
using Rubberduck . VBEditor ;
4
4
using System ;
5
5
using System . Collections . Generic ;
6
+ using System . Diagnostics ;
6
7
using System . Linq ;
7
8
using Antlr4 . Runtime ;
9
+ using Rubberduck . Parsing . Grammar ;
10
+ using Rubberduck . VBEditor . Application ;
8
11
9
12
namespace Rubberduck . Parsing . Symbols
10
13
{
14
+ internal static class DictionaryExtensions
15
+ {
16
+ public static IEnumerable < TValue > AllValues < TKey , TValue > (
17
+ this IDictionary < TKey , TValue [ ] > source )
18
+ {
19
+ return source . SelectMany ( item => item . Value ) ;
20
+ }
21
+
22
+ public static IEnumerable < TValue > AllValues < TKey , TValue > (
23
+ this IDictionary < TKey , IList < TValue > > source )
24
+ {
25
+ return source . SelectMany ( item => item . Value ) ;
26
+ }
27
+ }
28
+
11
29
public class DeclarationFinder
12
30
{
13
- //private readonly IDictionary<QualifiedModuleName, CommentNode[]> _comments;
31
+ private static readonly SquareBracketedNameComparer NameComparer = new SquareBracketedNameComparer ( ) ;
32
+
33
+ private readonly IHostApplication _hostApp ;
14
34
private readonly IDictionary < QualifiedModuleName , IAnnotation [ ] > _annotations ;
15
35
private readonly IDictionary < QualifiedMemberName , IList < Declaration > > _undeclared ;
16
36
private readonly AnnotationService _annotationService ;
17
37
18
- private readonly IReadOnlyList < Declaration > _declarations ;
38
+ private readonly IDictionary < QualifiedModuleName , Declaration [ ] > _declarations ;
19
39
private readonly IDictionary < string , Declaration [ ] > _declarationsByName ;
20
40
private static readonly Logger Logger = LogManager . GetCurrentClassLogger ( ) ;
21
41
22
- public DeclarationFinder (
23
- IReadOnlyList < Declaration > declarations ,
24
- IEnumerable < CommentNode > comments ,
25
- IEnumerable < IAnnotation > annotations )
42
+ public DeclarationFinder ( IReadOnlyList < Declaration > declarations , IEnumerable < IAnnotation > annotations , IHostApplication hostApp = null )
26
43
{
27
- //_comments = comments.GroupBy(node => node.QualifiedSelection.QualifiedName)
28
- // .ToDictionary(grouping => grouping.Key, grouping => grouping.ToArray());
44
+ _hostApp = hostApp ;
29
45
_annotations = annotations . GroupBy ( node => node . QualifiedSelection . QualifiedName )
30
46
. ToDictionary ( grouping => grouping . Key , grouping => grouping . ToArray ( ) ) ;
31
- _declarations = declarations ;
47
+ _declarations = declarations . GroupBy ( item => item . QualifiedName . QualifiedModuleName )
48
+ . ToDictionary ( grouping => grouping . Key , grouping => grouping . ToArray ( ) ) ;
32
49
_declarationsByName = declarations . GroupBy ( declaration => new
33
50
{
34
51
IdentifierName = declaration . IdentifierName . ToLowerInvariant ( )
35
52
} )
36
- . ToDictionary ( grouping => grouping . Key . IdentifierName , grouping => grouping . ToArray ( ) ) ;
53
+ . ToDictionary ( grouping => grouping . Key . IdentifierName , grouping => grouping . ToArray ( ) , NameComparer ) ;
37
54
38
55
_undeclared = new Dictionary < QualifiedMemberName , IList < Declaration > > ( ) ;
39
56
_annotationService = new AnnotationService ( this ) ;
40
57
}
41
58
42
59
public IEnumerable < Declaration > Undeclared
43
60
{
44
- get { return _undeclared . SelectMany ( e => e . Value ) ; }
61
+ get { return _undeclared . AllValues ( ) ; }
45
62
}
46
63
64
+ private IEnumerable < Declaration > _nonBaseAsType ;
47
65
public IEnumerable < Declaration > FindDeclarationsWithNonBaseAsType ( )
48
66
{
49
- return _declarations
67
+ return _nonBaseAsType ?? (
68
+ _nonBaseAsType = _declarations . AllValues ( )
50
69
. Where ( d =>
51
70
! string . IsNullOrWhiteSpace ( d . AsTypeName )
52
71
&& ! d . AsTypeIsBaseType
53
72
&& d . DeclarationType != DeclarationType . Project
54
- && d . DeclarationType != DeclarationType . ProceduralModule ) . ToList ( ) ;
73
+ && d . DeclarationType != DeclarationType . ProceduralModule ) . ToList ( ) ) ;
55
74
}
56
75
76
+ private IEnumerable < Declaration > _classes ;
57
77
public IEnumerable < Declaration > FindClasses ( )
58
78
{
59
- return _declarations . Where ( d => d . DeclarationType == DeclarationType . ClassModule ) . ToList ( ) ;
79
+ return _classes ?? (
80
+ _classes = _declarations . AllValues ( )
81
+ . Where ( d => d . DeclarationType == DeclarationType . ClassModule ) . ToList ( ) ) ;
60
82
}
61
83
84
+ private IEnumerable < Declaration > _projects ;
62
85
public IEnumerable < Declaration > FindProjects ( )
63
86
{
64
- return _declarations . Where ( d => d . DeclarationType == DeclarationType . Project ) . ToList ( ) ;
87
+ return _projects ?? (
88
+ _projects = _declarations . AllValues ( )
89
+ . Where ( d => d . DeclarationType == DeclarationType . Project ) . ToList ( ) ) ;
65
90
}
66
91
67
92
public Declaration FindParameter ( Declaration procedure , string parameterName )
@@ -77,7 +102,7 @@ public IEnumerable<IAnnotation> FindAnnotations(QualifiedModuleName module)
77
102
{
78
103
return result ;
79
104
}
80
- return new List < IAnnotation > ( ) ;
105
+ return Enumerable . Empty < IAnnotation > ( ) ;
81
106
}
82
107
83
108
public bool IsMatch ( string declarationName , string potentialMatchName )
@@ -101,11 +126,9 @@ public IEnumerable<Declaration> MatchName(string name)
101
126
{
102
127
var normalizedName = name . ToLowerInvariant ( ) ;
103
128
Declaration [ ] result ;
104
- if ( _declarationsByName . TryGetValue ( normalizedName , out result ) )
105
- {
106
- return result ;
107
- }
108
- return Enumerable . Empty < Declaration > ( ) ;
129
+ return _declarationsByName . TryGetValue ( normalizedName , out result )
130
+ ? result
131
+ : Enumerable . Empty < Declaration > ( ) ;
109
132
}
110
133
111
134
public Declaration FindProject ( string name , Declaration currentScope = null )
@@ -126,6 +149,7 @@ public Declaration FindProject(string name, Declaration currentScope = null)
126
149
127
150
public Declaration FindStdModule ( string name , Declaration parent = null , bool includeBuiltIn = false )
128
151
{
152
+ Debug . Assert ( parent != null ) ;
129
153
Declaration result = null ;
130
154
try
131
155
{
@@ -144,6 +168,7 @@ public Declaration FindStdModule(string name, Declaration parent = null, bool in
144
168
145
169
public Declaration FindClassModule ( string name , Declaration parent = null , bool includeBuiltIn = false )
146
170
{
171
+ Debug . Assert ( parent != null ) ;
147
172
Declaration result = null ;
148
173
try
149
174
{
@@ -283,7 +308,7 @@ public Declaration FindMemberEnclosingModule(Declaration callingModule, Declarat
283
308
284
309
public Declaration FindMemberEnclosingProcedure ( Declaration enclosingProcedure , string memberName , DeclarationType memberType , ParserRuleContext onSiteContext = null )
285
310
{
286
- if ( memberType == DeclarationType . Variable && enclosingProcedure . IdentifierName . Equals ( memberName ) )
311
+ if ( memberType == DeclarationType . Variable && NameComparer . Equals ( enclosingProcedure . IdentifierName , memberName ) )
287
312
{
288
313
return enclosingProcedure ;
289
314
}
@@ -322,6 +347,24 @@ public Declaration OnUndeclaredVariable(Declaration enclosingProcedure, string i
322
347
return undeclaredLocal ;
323
348
}
324
349
350
+ public Declaration OnBracketedExpression ( string expression , ParserRuleContext context )
351
+ {
352
+ var hostApp = FindProject ( _hostApp == null ? "VBA" : _hostApp . ApplicationName ) ;
353
+ var qualifiedName = hostApp . QualifiedName . QualifiedModuleName . QualifyMemberName ( expression ) ;
354
+
355
+ var exists = _undeclared . ContainsKey ( qualifiedName ) ;
356
+ if ( exists )
357
+ {
358
+ return _undeclared [ qualifiedName ] [ 0 ] ;
359
+ }
360
+ else
361
+ {
362
+ var item = new Declaration ( qualifiedName , hostApp , hostApp , Tokens . Variant , string . Empty , false , false , Accessibility . Global , DeclarationType . BracketedExpression , context , context . GetSelection ( ) , false , null ) ;
363
+ _undeclared . Add ( qualifiedName , new List < Declaration > { item } ) ;
364
+ return item ;
365
+ }
366
+ }
367
+
325
368
public Declaration FindMemberEnclosedProjectWithoutEnclosingModule ( Declaration callingProject , Declaration callingModule , Declaration callingParent , string memberName , DeclarationType memberType )
326
369
{
327
370
var allMatches = MatchName ( memberName ) ;
0 commit comments