1
1
using System ;
2
+ using System . Collections . Concurrent ;
2
3
using System . Collections . Generic ;
4
+ using System . Linq ;
3
5
using System . Threading ;
4
6
using Rubberduck . Parsing . VBA . Parsing . ParsingExceptions ;
5
7
using Rubberduck . VBEditor ;
@@ -36,23 +38,27 @@ protected ParseRunnerBase(
36
38
_parser = parser ;
37
39
}
38
40
41
+ public void ParseModules ( IReadOnlyCollection < QualifiedModuleName > modules , CancellationToken token )
42
+ {
43
+ var parseResults = ModulePareResults ( modules , token ) ;
44
+ SaveModuleParseResultsOnState ( parseResults , token ) ;
45
+ }
39
46
40
- public abstract void ParseModules ( IReadOnlyCollection < QualifiedModuleName > modules , CancellationToken token ) ;
41
-
47
+ protected abstract IReadOnlyCollection < ( QualifiedModuleName module , ModuleParseResults results ) > ModulePareResults ( IReadOnlyCollection < QualifiedModuleName > modules , CancellationToken token ) ;
42
48
43
- protected void ParseModule ( QualifiedModuleName module , CancellationToken token )
49
+ protected ModuleParseResults ModuleParseResults ( QualifiedModuleName module , CancellationToken token )
44
50
{
45
51
_state . ClearStateCache ( module ) ;
46
52
try
47
53
{
48
- var parseResults = _parser . Parse ( module , token ) ;
49
- SaveModuleParseResultsOnState ( module , parseResults , token ) ;
54
+ return _parser . Parse ( module , token ) ;
50
55
}
51
56
catch ( SyntaxErrorException syntaxErrorException )
52
57
{
53
58
//In contrast to the situation in the success scenario, the overall parser state is reevaluated immediately.
54
- //This sets the state directly on the state because it is the sole instance where we have to pass the SyntaxErorException .
59
+ //This sets the state directly on the state because it is the sole instance where we have to pass the SyntaxErrorException .
55
60
_state . SetModuleState ( module , ParserState . Error , token , syntaxErrorException ) ;
61
+ return default ;
56
62
}
57
63
catch ( Exception exception )
58
64
{
@@ -61,30 +67,40 @@ protected void ParseModule(QualifiedModuleName module, CancellationToken token)
61
67
}
62
68
}
63
69
64
- private void SaveModuleParseResultsOnState ( QualifiedModuleName module , ModuleParseResults results , CancellationToken token )
70
+ private void SaveModuleParseResultsOnState ( IReadOnlyCollection < ( QualifiedModuleName module , ModuleParseResults results ) > parseResults , CancellationToken token )
65
71
{
66
- lock ( _state )
72
+ foreach ( var ( module , result ) in parseResults )
67
73
{
68
- token . ThrowIfCancellationRequested ( ) ;
74
+ if ( result . CodePaneParseTree == null )
75
+ {
76
+ continue ;
77
+ }
69
78
70
- //This has to come first because it creates the module state if not present.
71
- _state . AddModuleStateIfNotPresent ( module ) ;
79
+ SaveModuleParseResultsOnState ( module , result , token ) ;
80
+ }
81
+ }
72
82
73
- _state . SaveContentHash ( module ) ;
74
- _state . AddParseTree ( module , results . CodePaneParseTree ) ;
75
- _state . AddParseTree ( module , results . AttributesParseTree , CodeKind . AttributesCode ) ;
76
- _state . SetModuleComments ( module , results . Comments ) ;
77
- _state . SetModuleAnnotations ( module , results . Annotations ) ;
78
- _state . SetModuleAttributes ( module , results . Attributes ) ;
79
- _state . SetMembersAllowingAttributes ( module , results . MembersAllowingAttributes ) ;
80
- _state . SetCodePaneTokenStream ( module , results . CodePaneTokenStream ) ;
81
- _state . SetAttributesTokenStream ( module , results . AttributesTokenStream ) ;
83
+ private void SaveModuleParseResultsOnState ( QualifiedModuleName module , ModuleParseResults results , CancellationToken token )
84
+ {
85
+ token . ThrowIfCancellationRequested ( ) ;
82
86
83
- // This really needs to go last
84
- //It does not reevaluate the overall parer state to avoid concurrent evaluation of all module states and for performance reasons.
85
- //The evaluation has to be triggered manually in the calling procedure.
86
- StateManager . SetModuleState ( module , ParserState . Parsed , token , false ) ; //Note that this is ok because locks allow re-entrancy.
87
- }
87
+ //This has to come first because it creates the module state if not present.
88
+ _state . AddModuleStateIfNotPresent ( module ) ;
89
+
90
+ _state . SaveContentHash ( module ) ;
91
+ _state . AddParseTree ( module , results . CodePaneParseTree ) ;
92
+ _state . AddParseTree ( module , results . AttributesParseTree , CodeKind . AttributesCode ) ;
93
+ _state . SetModuleComments ( module , results . Comments ) ;
94
+ _state . SetModuleAnnotations ( module , results . Annotations ) ;
95
+ _state . SetModuleAttributes ( module , results . Attributes ) ;
96
+ _state . SetMembersAllowingAttributes ( module , results . MembersAllowingAttributes ) ;
97
+ _state . SetCodePaneTokenStream ( module , results . CodePaneTokenStream ) ;
98
+ _state . SetAttributesTokenStream ( module , results . AttributesTokenStream ) ;
99
+
100
+ // This really needs to go last
101
+ //It does not reevaluate the overall parer state to avoid concurrent evaluation of all module states and for performance reasons.
102
+ //The evaluation has to be triggered manually in the calling procedure.
103
+ StateManager . SetModuleState ( module , ParserState . Parsed , token , false ) ; //Note that this is ok because locks allow re-entrancy.
88
104
}
89
105
}
90
106
}
0 commit comments