@@ -165,7 +165,7 @@ private void ParseAll()
165165 }
166166 }
167167
168- private readonly HashSet < ReferencePriorityMap > _references = new HashSet < ReferencePriorityMap > ( ) ;
168+ private readonly HashSet < ReferencePriorityMap > _projectReferences = new HashSet < ReferencePriorityMap > ( ) ;
169169
170170 private string GetReferenceProjectId ( Reference reference , IReadOnlyList < VBProject > projects )
171171 {
@@ -197,11 +197,11 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
197197 {
198198 var reference = vbProject . References . Item ( priority ) ;
199199 var referencedProjectId = GetReferenceProjectId ( reference , projects ) ;
200- var map = _references . SingleOrDefault ( r => r . ReferencedProjectId == referencedProjectId ) ;
200+ var map = _projectReferences . SingleOrDefault ( r => r . ReferencedProjectId == referencedProjectId ) ;
201201 if ( map == null )
202202 {
203203 map = new ReferencePriorityMap ( referencedProjectId ) { { projectId , priority } } ;
204- _references . Add ( map ) ;
204+ _projectReferences . Add ( map ) ;
205205 }
206206 else
207207 {
@@ -221,7 +221,7 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
221221 }
222222 }
223223
224- var mappedIds = _references . Select ( map => map . ReferencedProjectId ) ;
224+ var mappedIds = _projectReferences . Select ( map => map . ReferencedProjectId ) ;
225225 var unmapped = projects . SelectMany ( project => project . References . Cast < Reference > ( ) )
226226 . Where ( reference => ! mappedIds . Contains ( GetReferenceProjectId ( reference , projects ) ) ) ;
227227 foreach ( var reference in unmapped )
@@ -233,7 +233,7 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
233233 private void UnloadComReference ( Reference reference , IReadOnlyList < VBProject > projects )
234234 {
235235 var referencedProjectId = GetReferenceProjectId ( reference , projects ) ;
236- var map = _references . SingleOrDefault ( r => r . ReferencedProjectId == referencedProjectId ) ;
236+ var map = _projectReferences . SingleOrDefault ( r => r . ReferencedProjectId == referencedProjectId ) ;
237237 if ( map == null || ! map . IsLoaded )
238238 {
239239 // we're removing a reference we weren't tracking? ...this shouldn't happen.
@@ -243,7 +243,7 @@ private void UnloadComReference(Reference reference, IReadOnlyList<VBProject> pr
243243 map . Remove ( referencedProjectId ) ;
244244 if ( ! map . Any ( ) )
245245 {
246- _references . Remove ( map ) ;
246+ _projectReferences . Remove ( map ) ;
247247 _state . RemoveBuiltInDeclarations ( reference ) ;
248248 }
249249 }
@@ -338,7 +338,7 @@ private void ResolveInternal(CancellationToken token)
338338 {
339339 return ;
340340 }
341-
341+ _projectDeclarations . Clear ( ) ;
342342 foreach ( var kvp in _state . ParseTrees )
343343 {
344344 var qualifiedName = kvp . Key ;
@@ -370,6 +370,7 @@ private void ResolveInternal(CancellationToken token)
370370 }
371371 }
372372
373+ private readonly Dictionary < string , Declaration > _projectDeclarations = new Dictionary < string , Declaration > ( ) ;
373374 private void ResolveDeclarations ( VBComponent component , IParseTree tree )
374375 {
375376 var qualifiedModuleName = new QualifiedModuleName ( component ) ;
@@ -392,11 +393,15 @@ private void ResolveDeclarations(VBComponent component, IParseTree tree)
392393 _state . EmptyStringLiterals = emptyStringLiteralListener . Contexts . Select ( context => new QualifiedContext ( qualifiedModuleName , context ) ) ;
393394 _state . ObsoleteLetContexts = obsoleteLetStatementListener . Contexts . Select ( context => new QualifiedContext ( qualifiedModuleName , context ) ) ;
394395 _state . ObsoleteCallContexts = obsoleteCallStatementListener . Contexts . Select ( context => new QualifiedContext ( qualifiedModuleName , context ) ) ;
395-
396- // cannot locate declarations in one pass *the way it's currently implemented*,
397- // because the context in EnterSubStmt() doesn't *yet* have child nodes when the context enters.
398- // so we need to EnterAmbiguousIdentifier() and evaluate the parent instead - this *might* work.
399- var declarationsListener = new DeclarationSymbolsListener ( qualifiedModuleName , Accessibility . Implicit , component . Type , _state . GetModuleComments ( component ) , _state . GetModuleAnnotations ( component ) , _state . GetModuleAttributes ( component ) , _references ) ;
396+ var project = component . Collection . Parent ;
397+ var projectQualifiedName = new QualifiedModuleName ( project ) ;
398+ Declaration projectDeclaration ;
399+ if ( ! _projectDeclarations . TryGetValue ( projectQualifiedName . ProjectId , out projectDeclaration ) )
400+ {
401+ projectDeclaration = CreateProjectDeclaration ( projectQualifiedName , project ) ;
402+ _projectDeclarations . Add ( projectQualifiedName . ProjectId , projectDeclaration ) ;
403+ }
404+ var declarationsListener = new DeclarationSymbolsListener ( qualifiedModuleName , Accessibility . Implicit , component . Type , _state . GetModuleComments ( component ) , _state . GetModuleAnnotations ( component ) , _state . GetModuleAttributes ( component ) , _projectReferences , projectDeclaration ) ;
400405 // TODO: should we unify the API? consider working like the other listeners instead of event-based
401406 declarationsListener . NewDeclaration += ( sender , e ) => _state . AddDeclaration ( e . Declaration ) ;
402407 declarationsListener . CreateModuleDeclarations ( ) ;
@@ -408,7 +413,20 @@ private void ResolveDeclarations(VBComponent component, IParseTree tree)
408413 Debug . Print ( "Exception thrown resolving '{0}' (thread {2}): {1}" , component . Name , exception , Thread . CurrentThread . ManagedThreadId ) ;
409414 _state . SetModuleState ( component , ParserState . ResolverError ) ;
410415 }
416+ }
411417
418+ private Declaration CreateProjectDeclaration ( QualifiedModuleName projectQualifiedName , VBProject project )
419+ {
420+ var qualifiedName = projectQualifiedName . QualifyMemberName ( project . Name ) ;
421+ var projectId = qualifiedName . QualifiedModuleName . ProjectId ;
422+ var projectDeclaration = new ProjectDeclaration ( qualifiedName , project . Name ) ;
423+ var references = _projectReferences . Where ( projectContainingReference => projectContainingReference . ContainsKey ( projectId ) ) ;
424+ foreach ( var reference in references )
425+ {
426+ int priority = reference [ projectId ] ;
427+ projectDeclaration . AddProjectReference ( reference . ReferencedProjectId , priority ) ;
428+ }
429+ return projectDeclaration ;
412430 }
413431
414432 private void ResolveReferences ( DeclarationFinder finder , VBComponent component , IParseTree tree )
0 commit comments