@@ -50,23 +50,23 @@ public sealed class RubberduckParserState
50
50
private readonly ConcurrentDictionary < QualifiedModuleName , ConcurrentDictionary < Declaration , byte > > _declarations =
51
51
new ConcurrentDictionary < QualifiedModuleName , ConcurrentDictionary < Declaration , byte > > ( ) ;
52
52
53
- private readonly ConcurrentDictionary < VBComponent , ITokenStream > _tokenStreams =
54
- new ConcurrentDictionary < VBComponent , ITokenStream > ( ) ;
53
+ private readonly ConcurrentDictionary < QualifiedModuleName , ITokenStream > _tokenStreams =
54
+ new ConcurrentDictionary < QualifiedModuleName , ITokenStream > ( ) ;
55
55
56
- private readonly ConcurrentDictionary < VBComponent , IParseTree > _parseTrees =
57
- new ConcurrentDictionary < VBComponent , IParseTree > ( ) ;
56
+ private readonly ConcurrentDictionary < QualifiedModuleName , IParseTree > _parseTrees =
57
+ new ConcurrentDictionary < QualifiedModuleName , IParseTree > ( ) ;
58
58
59
- private readonly ConcurrentDictionary < VBComponent , ParserState > _moduleStates =
60
- new ConcurrentDictionary < VBComponent , ParserState > ( ) ;
59
+ private readonly ConcurrentDictionary < QualifiedModuleName , ParserState > _moduleStates =
60
+ new ConcurrentDictionary < QualifiedModuleName , ParserState > ( ) ;
61
61
62
- private readonly ConcurrentDictionary < VBComponent , IList < CommentNode > > _comments =
63
- new ConcurrentDictionary < VBComponent , IList < CommentNode > > ( ) ;
62
+ private readonly ConcurrentDictionary < QualifiedModuleName , IList < CommentNode > > _comments =
63
+ new ConcurrentDictionary < QualifiedModuleName , IList < CommentNode > > ( ) ;
64
64
65
- private readonly ConcurrentDictionary < VBComponent , SyntaxErrorException > _moduleExceptions =
66
- new ConcurrentDictionary < VBComponent , SyntaxErrorException > ( ) ;
65
+ private readonly ConcurrentDictionary < QualifiedModuleName , SyntaxErrorException > _moduleExceptions =
66
+ new ConcurrentDictionary < QualifiedModuleName , SyntaxErrorException > ( ) ;
67
67
68
- private readonly ConcurrentDictionary < VBComponent , IDictionary < Tuple < string , DeclarationType > , Attributes > > _moduleAttributes =
69
- new ConcurrentDictionary < VBComponent , IDictionary < Tuple < string , DeclarationType > , Attributes > > ( ) ;
68
+ private readonly ConcurrentDictionary < QualifiedModuleName , IDictionary < Tuple < string , DeclarationType > , Attributes > > _moduleAttributes =
69
+ new ConcurrentDictionary < QualifiedModuleName , IDictionary < Tuple < string , DeclarationType > , Attributes > > ( ) ;
70
70
71
71
public void AddProject ( VBProject project )
72
72
{
@@ -90,7 +90,7 @@ public void RemoveProject(VBProject project)
90
90
91
91
public IReadOnlyList < Tuple < VBComponent , SyntaxErrorException > > ModuleExceptions
92
92
{
93
- get { return _moduleExceptions . Select ( kvp => Tuple . Create ( kvp . Key , kvp . Value ) ) . Where ( item => item . Item2 != null ) . ToList ( ) ; }
93
+ get { return _moduleExceptions . Select ( kvp => Tuple . Create ( kvp . Key . Component , kvp . Value ) ) . Where ( item => item . Item2 != null ) . ToList ( ) ; }
94
94
}
95
95
96
96
public event EventHandler < ParserStateEventArgs > StateChanged ;
@@ -117,30 +117,77 @@ private void OnModuleStateChanged(VBComponent component, ParserState state)
117
117
118
118
public void SetModuleState ( VBComponent component , ParserState state , SyntaxErrorException parserError = null )
119
119
{
120
- _moduleStates . AddOrUpdate ( component , state , ( c , s ) => state ) ;
121
- _moduleExceptions . AddOrUpdate ( component , parserError , ( c , e ) => parserError ) ;
120
+ if ( AllUserDeclarations . Any ( ) )
121
+ {
122
+ var projectName = component . ProjectName ( ) ;
123
+ var project = AllUserDeclarations . SingleOrDefault ( item =>
124
+ item . DeclarationType == DeclarationType . Project && item . ProjectName == projectName ) ;
125
+
126
+ if ( project == null )
127
+ {
128
+ // ghost component shouldn't even exist
129
+ ClearDeclarations ( component ) ;
130
+ return ;
131
+ }
132
+ }
133
+ var key = new QualifiedModuleName ( component ) ;
134
+ _moduleStates . AddOrUpdate ( key , state , ( c , s ) => state ) ;
135
+ _moduleExceptions . AddOrUpdate ( key , parserError , ( c , e ) => parserError ) ;
122
136
123
- Debug . WriteLine ( "Module '{0}' state is changing to '{1}' (thread {2})" , component . Name , state , Thread . CurrentThread . ManagedThreadId ) ;
137
+ Debug . WriteLine ( "Module '{0}' state is changing to '{1}' (thread {2})" , key . ComponentName , state , Thread . CurrentThread . ManagedThreadId ) ;
124
138
OnModuleStateChanged ( component , state ) ;
125
139
126
140
Status = EvaluateParserState ( ) ;
127
141
}
128
142
143
+ private static readonly ParserState [ ] States = Enum . GetValues ( typeof ( ParserState ) ) . Cast < ParserState > ( ) . ToArray ( ) ;
129
144
private ParserState EvaluateParserState ( )
130
145
{
131
146
var moduleStates = _moduleStates . Values . ToList ( ) ;
132
147
133
- var prelim = moduleStates . Max ( ) ;
134
- if ( prelim == ParserState . Parsed && moduleStates . Any ( s => s != ParserState . Parsed ) )
148
+ var state = States . SingleOrDefault ( value => moduleStates . All ( ps => ps == value ) ) ;
149
+ if ( state != default ( ParserState ) )
150
+ {
151
+ // if all modules are in the same state, we have our result.
152
+ Debug . WriteLine ( "ParserState evaluates to '{0}' (thread {1})" , state , Thread . CurrentThread . ManagedThreadId ) ;
153
+ return state ;
154
+ }
155
+
156
+ // error state takes precedence over every other state
157
+ if ( moduleStates . Any ( ms => ms == ParserState . Error ) )
158
+ {
159
+ Debug . WriteLine ( "ParserState evaluates to '{0}' (thread {1})" , ParserState . Error , Thread . CurrentThread . ManagedThreadId ) ;
160
+ return ParserState . Error ;
161
+ }
162
+ if ( moduleStates . Any ( ms => ms == ParserState . ResolverError ) )
163
+ {
164
+ Debug . WriteLine ( "ParserState evaluates to '{0}' (thread {1})" , ParserState . ResolverError , Thread . CurrentThread . ManagedThreadId ) ;
165
+ return ParserState . ResolverError ;
166
+ }
167
+
168
+ // "working" states are toggled when *any* module has them.
169
+ var result = moduleStates . Min ( ) ;
170
+ if ( moduleStates . Any ( ms => ms == ParserState . LoadingReference ) )
135
171
{
136
- prelim = moduleStates . Where ( s => s != ParserState . Parsed ) . Max ( ) ;
172
+ result = ParserState . LoadingReference ;
137
173
}
138
- return prelim ;
174
+ if ( moduleStates . Any ( ms => ms == ParserState . Parsing ) )
175
+ {
176
+ result = ParserState . Parsing ;
177
+ }
178
+ if ( moduleStates . Any ( ms => ms == ParserState . Resolving ) )
179
+ {
180
+ result = ParserState . Resolving ;
181
+ }
182
+
183
+ // otherwise, return the
184
+ Debug . WriteLine ( "ParserState evaluates to '{0}' (thread {1})" , result , Thread . CurrentThread . ManagedThreadId ) ;
185
+ return result ;
139
186
}
140
187
141
188
public ParserState GetModuleState ( VBComponent component )
142
189
{
143
- return _moduleStates . GetOrAdd ( component , ParserState . Pending ) ;
190
+ return _moduleStates . GetOrAdd ( new QualifiedModuleName ( component ) , ParserState . Pending ) ;
144
191
}
145
192
146
193
private ParserState _status ;
@@ -182,7 +229,7 @@ public IEnumerable<QualifiedContext> ObsoleteLetContexts
182
229
183
230
internal void SetModuleAttributes ( VBComponent component , IDictionary < Tuple < string , DeclarationType > , Attributes > attributes )
184
231
{
185
- _moduleAttributes . AddOrUpdate ( component , attributes , ( c , s ) => attributes ) ;
232
+ _moduleAttributes . AddOrUpdate ( new QualifiedModuleName ( component ) , attributes , ( c , s ) => attributes ) ;
186
233
}
187
234
188
235
private IEnumerable < QualifiedContext > _emptyStringLiterals = new List < QualifiedContext > ( ) ;
@@ -214,7 +261,7 @@ public IEnumerable<CommentNode> AllComments
214
261
public IEnumerable < CommentNode > GetModuleComments ( VBComponent component )
215
262
{
216
263
IList < CommentNode > result ;
217
- if ( _comments . TryGetValue ( component , out result ) )
264
+ if ( _comments . TryGetValue ( new QualifiedModuleName ( component ) , out result ) )
218
265
{
219
266
return result ;
220
267
}
@@ -224,7 +271,7 @@ public IEnumerable<CommentNode> GetModuleComments(VBComponent component)
224
271
225
272
public void SetModuleComments ( VBComponent component , IEnumerable < CommentNode > comments )
226
273
{
227
- _comments [ component ] = comments . ToList ( ) ;
274
+ _comments [ new QualifiedModuleName ( component ) ] = comments . ToList ( ) ;
228
275
}
229
276
230
277
/// <summary>
@@ -254,7 +301,7 @@ public IReadOnlyList<Declaration> AllUserDeclarations
254
301
255
302
internal IDictionary < Tuple < string , DeclarationType > , Attributes > getModuleAttributes ( VBComponent vbComponent )
256
303
{
257
- return _moduleAttributes [ vbComponent ] ;
304
+ return _moduleAttributes [ new QualifiedModuleName ( vbComponent ) ] ;
258
305
}
259
306
260
307
/// <summary>
@@ -319,19 +366,19 @@ public bool ClearDeclarations(VBComponent component)
319
366
declarationsRemoved = declarations == null ? 0 : declarations . Count ;
320
367
321
368
IParseTree tree ;
322
- success = success && ( ! _parseTrees . ContainsKey ( key . Component ) || _parseTrees . TryRemove ( key . Component , out tree ) ) ;
369
+ success = success && ( ! _parseTrees . ContainsKey ( key ) || _parseTrees . TryRemove ( key , out tree ) ) ;
323
370
324
371
ITokenStream stream ;
325
- success = success && ( ! _tokenStreams . ContainsKey ( key . Component ) || _tokenStreams . TryRemove ( key . Component , out stream ) ) ;
372
+ success = success && ( ! _tokenStreams . ContainsKey ( key ) || _tokenStreams . TryRemove ( key , out stream ) ) ;
326
373
327
374
ParserState state ;
328
- success = success && ( ! _moduleStates . ContainsKey ( key . Component ) || _moduleStates . TryRemove ( key . Component , out state ) ) ;
375
+ success = success && ( ! _moduleStates . ContainsKey ( key ) || _moduleStates . TryRemove ( key , out state ) ) ;
329
376
330
377
SyntaxErrorException exception ;
331
- success = success && ( ! _moduleExceptions . ContainsKey ( key . Component ) || _moduleExceptions . TryRemove ( key . Component , out exception ) ) ;
378
+ success = success && ( ! _moduleExceptions . ContainsKey ( key ) || _moduleExceptions . TryRemove ( key , out exception ) ) ;
332
379
333
380
IList < CommentNode > nodes ;
334
- success = success && ( ! _comments . ContainsKey ( key . Component ) || _comments . TryRemove ( key . Component , out nodes ) ) ;
381
+ success = success && ( ! _comments . ContainsKey ( key ) || _comments . TryRemove ( key , out nodes ) ) ;
335
382
}
336
383
337
384
Debug . WriteLine ( "ClearDeclarations({0}): {1} - {2} declarations removed" , component . Name , success ? "succeeded" : "failed" , declarationsRemoved ) ;
@@ -340,24 +387,24 @@ public bool ClearDeclarations(VBComponent component)
340
387
341
388
public void AddTokenStream ( VBComponent component , ITokenStream stream )
342
389
{
343
- _tokenStreams [ component ] = stream ;
390
+ _tokenStreams [ new QualifiedModuleName ( component ) ] = stream ;
344
391
}
345
392
346
393
public void AddParseTree ( VBComponent component , IParseTree parseTree )
347
394
{
348
- _parseTrees [ component ] = parseTree ;
395
+ _parseTrees [ new QualifiedModuleName ( component ) ] = parseTree ;
349
396
}
350
397
351
398
public IParseTree GetParseTree ( VBComponent component )
352
399
{
353
- return _parseTrees [ component ] ;
400
+ return _parseTrees [ new QualifiedModuleName ( component ) ] ;
354
401
}
355
402
356
- public IEnumerable < KeyValuePair < VBComponent , IParseTree > > ParseTrees { get { return _parseTrees ; } }
403
+ public IEnumerable < KeyValuePair < QualifiedModuleName , IParseTree > > ParseTrees { get { return _parseTrees ; } }
357
404
358
405
public TokenStreamRewriter GetRewriter ( VBComponent component )
359
406
{
360
- return new TokenStreamRewriter ( _tokenStreams [ component ] ) ;
407
+ return new TokenStreamRewriter ( _tokenStreams [ new QualifiedModuleName ( component ) ] ) ;
361
408
}
362
409
363
410
/// <summary>
0 commit comments