Guest User

Untitled

a guest
Nov 26th, 2015
31
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Diff 27.35 KB | None | 0 0
  1. diff --git a/RetailCoder.VBE/App.cs b/RetailCoder.VBE/App.cs
  2. index 69dbf04..1180eb8 100644
  3. --- a/RetailCoder.VBE/App.cs
  4. +++ b/RetailCoder.VBE/App.cs
  5. @@ -1,6 +1,7 @@
  6.  using System;
  7.  using System.Collections.Concurrent;
  8.  using System.Collections.Generic;
  9. +using System.Diagnostics;
  10.  using System.Globalization;
  11.  using System.Linq;
  12.  using System.Runtime.InteropServices;
  13. @@ -8,10 +9,13 @@ using System.Threading;
  14.  using System.Threading.Tasks;
  15.  using System.Windows.Forms;
  16.  using Microsoft.Vbe.Interop;
  17. +using Nito.AsyncEx;
  18.  using NLog;
  19.  using Rubberduck.Common;
  20.  using Rubberduck.Inspections;
  21.  using Rubberduck.Parsing;
  22. +using Rubberduck.Parsing.Symbols;
  23. +using Rubberduck.Parsing.VBA;
  24.  using Rubberduck.Settings;
  25.  using Rubberduck.UI;
  26.  using Rubberduck.UI.Command.MenuItems;
  27. @@ -36,8 +40,8 @@ namespace Rubberduck
  28.  
  29.          private Configuration _config;
  30.  
  31. -        private readonly ConcurrentDictionary<VBComponent, CancellationTokenSource> _tokenSources =
  32. -            new ConcurrentDictionary<VBComponent, CancellationTokenSource>();
  33. +        //private readonly ConcurrentDictionary<VBComponent, CancellationTokenSource> _tokenSources =
  34. +        //    new ConcurrentDictionary<VBComponent, CancellationTokenSource>();
  35.  
  36.          public App(VBE vbe, IMessageBox messageBox,
  37.              IParserErrorsPresenterFactory parserErrorsPresenterFactory,
  38. @@ -67,7 +71,7 @@ namespace Rubberduck
  39.  
  40.          private void _stateBar_Refresh(object sender, EventArgs e)
  41.          {
  42. -            Task.Run(() => ParseAll());
  43. +            //Task.Run(() => ParseAll());
  44.          }
  45.  
  46.          private void Parser_StateChanged(object sender, EventArgs e)
  47. @@ -77,38 +81,86 @@ namespace Rubberduck
  48.  
  49.          private async void _hook_KeyPressed(object sender, KeyHookEventArgs e)
  50.          {
  51. -            await ParseComponentAsync(e.Component);
  52. +            try
  53. +            {
  54. +                await ParseComponentAsync(e.Component, resolve: true);
  55. +            }
  56. +            catch (SyntaxErrorException ex)
  57. +            {
  58. +                Debug.WriteLine(ex.Message);
  59. +            }
  60. +            finally
  61. +            {
  62. +                _parser.State.SetModuleState(e.Component, ParserState.Ready);
  63. +            }
  64.          }
  65.  
  66. +        //private readonly Dictionary<VBComponent, Task> _parseTasks = new Dictionary<VBComponent, Task>();
  67. +
  68. +        private readonly AsyncLock _lock = new AsyncLock();
  69. +
  70. +        private CancellationTokenSource _cancellationTokenSource;
  71. +
  72. +        private Task _parseTask;
  73. +
  74.          private async Task ParseComponentAsync(VBComponent component, bool resolve = true)
  75.          {
  76. -            var tokenSource = RenewTokenSource(component);
  77. +            _cancellationTokenSource?.Cancel();
  78.  
  79. -            var token = tokenSource.Token;
  80. -            await _parser.ParseAsync(component, token);
  81. +            using (await _lock.LockAsync())
  82. +            {
  83. +                _cancellationTokenSource = new CancellationTokenSource();
  84. +                _parseTask = ParseTaskHelper(component, resolve, _cancellationTokenSource.Token);
  85. +            }
  86.  
  87. -            if (resolve && !token.IsCancellationRequested)
  88. +            try
  89.              {
  90. -                using (var source = new CancellationTokenSource())
  91. -                {
  92. -                    _parser.Resolve(source.Token);
  93. -                }
  94. +                await _parseTask;
  95. +            }
  96. +            catch (OperationCanceledException e)
  97. +            {
  98. +                Debug.WriteLine(e.Message);
  99.              }
  100.          }
  101.  
  102. -        private CancellationTokenSource RenewTokenSource(VBComponent component)
  103. +        private async Task ParseTaskHelper(VBComponent component, bool resolve, CancellationToken cancellationToken)
  104.          {
  105. -            if (_tokenSources.ContainsKey(component))
  106. +            try
  107.              {
  108. -                CancellationTokenSource existingTokenSource;
  109. -                _tokenSources.TryRemove(component, out existingTokenSource);
  110. -                existingTokenSource.Cancel();
  111. -                existingTokenSource.Dispose();
  112. +                if (_parseTask != null)
  113. +                {
  114. +                    await _parseTask;
  115. +                }
  116.              }
  117. +            catch (OperationCanceledException)
  118. +            {
  119. +            }
  120. +            catch (Exception e)
  121. +            {
  122. +                Debugger.Break();
  123. +            }
  124. +
  125. +            //cancellationToken.ThrowIfCancellationRequested();
  126.  
  127. -            var tokenSource = new CancellationTokenSource();
  128. -            _tokenSources[component] = tokenSource;
  129. -            return tokenSource;
  130. +            try
  131. +            {
  132. +                // Parse is a long-running, blocking, CPU-bound operation.
  133. +                // Offload the work to the thread pool to keep the UI responsive.
  134. +                await Task.Run(() => _parser.Parse(component, cancellationToken), cancellationToken);
  135. +
  136. +                //if (resolve)
  137. +                //{
  138. +                //    cancellationToken.ThrowIfCancellationRequested();
  139. +                //    await Task.Run(() => _parser.Resolve(cancellationToken), cancellationToken);
  140. +                //}
  141. +            }
  142. +            catch (OperationCanceledException)
  143. +            {
  144. +            }
  145. +            catch (Exception e)
  146. +            {
  147. +                //Debugger.Break();
  148. +            }
  149.          }
  150.  
  151.          public void Startup()
  152. @@ -132,15 +184,15 @@ namespace Rubberduck
  153.              var components = _vbe.VBProjects.Cast<VBProject>()
  154.                  .SelectMany(project => project.VBComponents.Cast<VBComponent>());
  155.  
  156. -            var result = Parallel.ForEach(components, async component => { await ParseComponentAsync(component, false); });
  157. +            //var result = Parallel.ForEach(components, component => ParseComponentAsync(component, false));
  158.  
  159. -            if (result.IsCompleted)
  160. -            {
  161. -                using (var tokenSource = new CancellationTokenSource())
  162. -                {
  163. -                    _parser.Resolve(tokenSource.Token);
  164. -                }
  165. -            }
  166. +            //if (result.IsCompleted)
  167. +            //{
  168. +            //    using (var tokenSource = new CancellationTokenSource())
  169. +            //    {
  170. +            //        _parser.Resolve(tokenSource.Token);
  171. +            //    }
  172. +            //}
  173.          }
  174.  
  175.          private void CleanReloadConfig()
  176. @@ -186,14 +238,14 @@ namespace Rubberduck
  177.              _configService.SettingsChanged -= _configService_SettingsChanged;
  178.              _parser.State.StateChanged -= Parser_StateChanged;
  179.  
  180. -            if (_tokenSources.Any())
  181. -            {
  182. -                foreach (var tokenSource in _tokenSources)
  183. -                {
  184. -                    tokenSource.Value.Cancel();
  185. -                    tokenSource.Value.Dispose();
  186. -                }
  187. -            }
  188. +            //if (_tokenSources.Any())
  189. +            //{
  190. +            //    foreach (var tokenSource in _tokenSources)
  191. +            //    {
  192. +            //        tokenSource.Value.Cancel();
  193. +            //        tokenSource.Value.Dispose();
  194. +            //    }
  195. +            //}
  196.          }
  197.      }
  198.  }
  199. diff --git a/RetailCoder.VBE/Common/KeyHook.cs b/RetailCoder.VBE/Common/KeyHook.cs
  200. index cb2b15d..df6254d 100644
  201. --- a/RetailCoder.VBE/Common/KeyHook.cs
  202. +++ b/RetailCoder.VBE/Common/KeyHook.cs
  203. @@ -1,7 +1,9 @@
  204.  using System;
  205. +using System.Collections.Concurrent;
  206.  using System.Diagnostics;
  207.  using System.Linq;
  208.  using System.Runtime.InteropServices;
  209. +using System.Threading;
  210.  using System.Threading.Tasks;
  211.  using System.Windows.Forms;
  212.  using Microsoft.Vbe.Interop;
  213. @@ -20,17 +22,13 @@ namespace Rubberduck.Common
  214.          private readonly VBE _vbe;
  215.          // reference: http://blogs.msdn.com/b/toub/archive/2006/05/03/589423.aspx
  216.  
  217. -        private const int WH_KEYBOARD_LL = 13;
  218. -        private const int WM_KEYDOWN = 0x0100;
  219. -        private const int WM_KEYUP = 0x0101;
  220. -
  221. -        private readonly LowLevelKeyboardProc _proc;
  222. +        private readonly HookProcedure _proc;
  223.          private static IntPtr HookId = IntPtr.Zero;
  224.  
  225. -        private delegate IntPtr LowLevelKeyboardProc(int nCode, IntPtr wParam, IntPtr lParam);
  226. +        private delegate IntPtr HookProcedure(int nCode, IntPtr wParam, IntPtr lParam);
  227.  
  228.          [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  229. -        private static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId);
  230. +        private static extern IntPtr SetWindowsHookEx(int idHook, HookProcedure lpfn, IntPtr hMod, uint dwThreadId);
  231.  
  232.          [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  233.          [return: MarshalAs(UnmanagedType.Bool)]
  234. @@ -39,22 +37,14 @@ namespace Rubberduck.Common
  235.          [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  236.          private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, IntPtr wParam, IntPtr lParam);
  237.  
  238. -        [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  239. -        private static extern IntPtr GetModuleHandle(string lpModuleName);
  240. -
  241. -        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  242. -        private static extern IntPtr GetForegroundWindow();
  243. -
  244. -        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
  245. -        private static extern IntPtr GetWindowThreadProcessId(IntPtr handle, out int processID);
  246. +        [DllImport("kernel32", CharSet = CharSet.Auto, SetLastError = true)]
  247. +        public static extern int GetCurrentThreadId();
  248.  
  249. -        private static IntPtr SetHook(LowLevelKeyboardProc proc)
  250. +        private static IntPtr SetHook(HookProcedure procedure)
  251.          {
  252. -            using (var curProcess = Process.GetCurrentProcess())
  253. -            using (var curModule = curProcess.MainModule)
  254. -            {
  255. -                return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
  256. -            }
  257. +            const int WH_KEYBOARD = 2;
  258. +            var threadId = (uint)GetCurrentThreadId();
  259. +            return SetWindowsHookEx(WH_KEYBOARD, procedure, IntPtr.Zero, threadId);
  260.          }
  261.  
  262.          private static readonly Keys[] IgnoredKeys =
  263. @@ -79,30 +69,46 @@ namespace Rubberduck.Common
  264.              Keys.RControlKey,
  265.          };
  266.  
  267. -        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
  268. +        private readonly BlockingCollection<Keys> _keys = new BlockingCollection<Keys>(new ConcurrentQueue<Keys>());
  269. +
  270. +        private void ConsumeKeys()
  271.          {
  272. -            var vkCode = Marshal.ReadInt32(lParam);
  273. -            var key = (Keys)vkCode;
  274. +            foreach (var key in _keys.GetConsumingEnumerable())
  275. +            {
  276. +                if (IgnoredKeys.Contains(key))
  277. +                {
  278. +                    continue;
  279. +                }
  280. +
  281. +                VBComponent component;
  282. +                try
  283. +                {
  284. +                    component = _vbe.ActiveCodePane?.CodeModule?.Parent;
  285. +                }
  286. +                catch (COMException)
  287. +                {
  288. +                    continue;
  289. +                }
  290. +
  291. +                if (component == null)
  292. +                {
  293. +                    continue;
  294. +                }
  295.  
  296. -            var windowHandle = GetForegroundWindow();
  297. -            var vbeWindow = _vbe.MainWindow.HWnd;
  298. -            var codePane = _vbe.ActiveCodePane;
  299. +                OnKeyPressed(new KeyHookEventArgs(key, component));
  300. +            }
  301. +        }
  302.  
  303. -            Task.Run(() =>
  304. +        private IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
  305. +        {
  306. +            if (nCode >= 0)
  307.              {
  308. -                if (windowHandle != (IntPtr) vbeWindow
  309. -                    || wParam != (IntPtr) WM_KEYUP
  310. -                    || nCode < 0
  311. -                    || codePane == null
  312. -                    || IgnoredKeys.Contains(key))
  313. +                if (((int) lParam & (1 << 31)) != 0)
  314.                  {
  315. -                    return;
  316. +                    var key = (Keys) wParam;
  317. +                    _keys.Add(key);
  318.                  }
  319. -
  320. -                var component = codePane.CodeModule.Parent;
  321. -                var args = new KeyHookEventArgs(key, component);
  322. -                OnKeyPressed(args);
  323. -            });
  324. +            }
  325.  
  326.              return CallNextHookEx(HookId, nCode, wParam, lParam);
  327.          }
  328. @@ -115,11 +121,13 @@ namespace Rubberduck.Common
  329.  
  330.          public void Attach()
  331.          {
  332. +            new Thread(() => ConsumeKeys()).Start();
  333.              HookId = SetHook(_proc);
  334.          }
  335.  
  336.          public void Detach()
  337.          {
  338. +            _keys.CompleteAdding();
  339.              UnhookWindowsHookEx(HookId);
  340.          }
  341.  
  342. diff --git a/RetailCoder.VBE/Rubberduck.csproj b/RetailCoder.VBE/Rubberduck.csproj
  343. index 07e333d..cd7574f 100644
  344. --- a/RetailCoder.VBE/Rubberduck.csproj
  345. +++ b/RetailCoder.VBE/Rubberduck.csproj
  346. @@ -237,6 +237,18 @@
  347.      <Reference Include="Ninject.Extensions.NamedScope">
  348.        <HintPath>..\packages\Ninject.Extensions.NamedScope.3.2.0.0\lib\net45-full\Ninject.Extensions.NamedScope.dll</HintPath>
  349.      </Reference>
  350. +    <Reference Include="Nito.AsyncEx, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
  351. +      <HintPath>..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.dll</HintPath>
  352. +      <Private>True</Private>
  353. +    </Reference>
  354. +    <Reference Include="Nito.AsyncEx.Concurrent, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
  355. +      <HintPath>..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Concurrent.dll</HintPath>
  356. +      <Private>True</Private>
  357. +    </Reference>
  358. +    <Reference Include="Nito.AsyncEx.Enlightenment, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
  359. +      <HintPath>..\packages\Nito.AsyncEx.3.0.1\lib\net45\Nito.AsyncEx.Enlightenment.dll</HintPath>
  360. +      <Private>True</Private>
  361. +    </Reference>
  362.      <Reference Include="PresentationCore" />
  363.      <Reference Include="PresentationFramework" />
  364.      <Reference Include="stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
  365. diff --git a/RetailCoder.VBE/packages.config b/RetailCoder.VBE/packages.config
  366. index 51e53e7..98f4be8 100644
  367. --- a/RetailCoder.VBE/packages.config
  368. +++ b/RetailCoder.VBE/packages.config
  369. @@ -7,6 +7,7 @@
  370.    <package id="Ninject.Extensions.Conventions" version="3.2.0.0" targetFramework="net45" />
  371.    <package id="Ninject.Extensions.Factory" version="3.2.1.0" targetFramework="net45" />
  372.    <package id="Ninject.Extensions.NamedScope" version="3.2.0.0" targetFramework="net45" />
  373. +  <package id="Nito.AsyncEx" version="3.0.1" targetFramework="net45" />
  374.    <package id="NLog" version="4.0.1" targetFramework="net45" />
  375.    <package id="NLog.Schema" version="4.0.1" targetFramework="net45" />
  376.  </packages>
  377. \ No newline at end of file
  378. diff --git a/Rubberduck.Parsing/IRubberduckParser.cs b/Rubberduck.Parsing/IRubberduckParser.cs
  379. index e175182..d683afc 100644
  380. --- a/Rubberduck.Parsing/IRubberduckParser.cs
  381. +++ b/Rubberduck.Parsing/IRubberduckParser.cs
  382. @@ -1,5 +1,4 @@
  383.  using System.Threading;
  384. -using System.Threading.Tasks;
  385.  using Microsoft.Vbe.Interop;
  386.  using Rubberduck.Parsing.VBA;
  387.  
  388. @@ -8,7 +7,7 @@ namespace Rubberduck.Parsing
  389.      public interface IRubberduckParser
  390.      {
  391.          RubberduckParserState State { get; }
  392. -        Task ParseAsync(VBComponent component, CancellationToken token);
  393. +        void Parse(VBComponent component, CancellationToken token);
  394.          void Resolve(CancellationToken token);
  395.      }
  396.  }
  397. \ No newline at end of file
  398. diff --git a/Rubberduck.Parsing/Symbols/Declaration.cs b/Rubberduck.Parsing/Symbols/Declaration.cs
  399. index 415115e..805c581 100644
  400. --- a/Rubberduck.Parsing/Symbols/Declaration.cs
  401. +++ b/Rubberduck.Parsing/Symbols/Declaration.cs
  402. @@ -319,6 +319,16 @@ namespace Rubberduck.Parsing.Symbols
  403.  
  404.          public bool Equals(Declaration other)
  405.          {
  406. +            if (object.ReferenceEquals(other, null))
  407. +            {
  408. +                return false;
  409. +            }
  410. +
  411. +            if (object.ReferenceEquals(other, this))
  412. +            {
  413. +                return true;
  414. +            }
  415. +
  416.              return other.Project == Project
  417.                  && other.IdentifierName == IdentifierName
  418.                  && other.DeclarationType == DeclarationType
  419. @@ -333,7 +343,29 @@ namespace Rubberduck.Parsing.Symbols
  420.  
  421.          public override int GetHashCode()
  422.          {
  423. -            return string.Concat(QualifiedName.QualifiedModuleName.ProjectHashCode, _identifierName, _declarationType, Scope, _parentScope).GetHashCode();
  424. +            unchecked
  425. +            {
  426. +                var hash = 17;
  427. +                if (Project != null)
  428. +                {
  429. +                    hash = hash * 23 + Project.GetHashCode();
  430. +                }
  431. +                if (IdentifierName != null)
  432. +                {
  433. +                    hash = hash * 23 + IdentifierName.GetHashCode();
  434. +                }
  435. +                hash = hash * 23 + DeclarationType.GetHashCode();
  436. +                if (Scope != null)
  437. +                {
  438. +                    hash = hash * 23 + Scope.GetHashCode();
  439. +                }
  440. +                if (ParentScope != null)
  441. +                {
  442. +                    hash = hash * 23 + ParentScope.GetHashCode();
  443. +                }
  444. +                return hash;
  445. +            }
  446. +            //return string.Concat(QualifiedName.QualifiedModuleName.ProjectHashCode, _identifierName, _declarationType, Scope, _parentScope).GetHashCode();
  447.          }
  448.      }
  449.  }
  450. diff --git a/Rubberduck.Parsing/VBA/RubberduckParser.cs b/Rubberduck.Parsing/VBA/RubberduckParser.cs
  451. index c1801dd..c022372 100644
  452. --- a/Rubberduck.Parsing/VBA/RubberduckParser.cs
  453. +++ b/Rubberduck.Parsing/VBA/RubberduckParser.cs
  454. @@ -1,7 +1,5 @@
  455. -using System;
  456. -using System.Collections.Generic;
  457. +using System.Collections.Generic;
  458.  using System.Linq;
  459. -using System.Runtime.InteropServices;
  460.  using System.Text;
  461.  using System.Threading;
  462.  using System.Threading.Tasks;
  463. @@ -33,24 +31,54 @@ namespace Rubberduck.Parsing.VBA
  464.          private readonly RubberduckParserState _state;
  465.          public RubberduckParserState State { get { return _state; } }
  466.  
  467. -        public async Task ParseAsync(VBComponent vbComponent, CancellationToken token)
  468. +        public void Parse(VBComponent vbComponent, CancellationToken token)
  469.          {
  470. -            var component = vbComponent;
  471. +            _state.ClearDeclarations(vbComponent, token);
  472.  
  473. -            var parseTask = Task.Run(() => ParseInternal(component, token), token);
  474. +            token.ThrowIfCancellationRequested();
  475.  
  476. -            try
  477. -            {
  478. -                await parseTask;
  479. -            }
  480. -            catch (SyntaxErrorException exception)
  481. -            {
  482. -                State.SetModuleState(component, ParserState.Error, exception);
  483. -            }
  484. -            catch (OperationCanceledException)
  485. +            State.SetModuleState(vbComponent, ParserState.Parsing);
  486. +
  487. +            var qualifiedName = new QualifiedModuleName(vbComponent);
  488. +            _state.SetModuleComments(vbComponent, ParseComments(qualifiedName));
  489. +
  490. +            var obsoleteCallsListener = new ObsoleteCallStatementListener();
  491. +            var obsoleteLetListener = new ObsoleteLetStatementListener();
  492. +
  493. +            var listeners = new IParseTreeListener[]
  494.              {
  495. -                // no need to blow up
  496. -            }
  497. +                obsoleteCallsListener,
  498. +                obsoleteLetListener
  499. +            };
  500. +
  501. +            token.ThrowIfCancellationRequested();
  502. +
  503. +            ITokenStream stream;
  504. +            var code = string.Join("\r\n", vbComponent.CodeModule.Code());
  505. +            var tree = ParseInternal(code, listeners, out stream);
  506. +
  507. +            token.ThrowIfCancellationRequested();
  508. +            _state.AddTokenStream(vbComponent, stream);
  509. +            _state.AddParseTree(vbComponent, tree);
  510. +
  511. +            // cannot locate declarations in one pass *the way it's currently implemented*,
  512. +            // because the context in EnterSubStmt() doesn't *yet* have child nodes when the context enters.
  513. +            // so we need to EnterAmbiguousIdentifier() and evaluate the parent instead - this *might* work.
  514. +            var declarationsListener = new DeclarationSymbolsListener(qualifiedName, Accessibility.Implicit, vbComponent.Type, _state.Comments, token);
  515. +
  516. +            token.ThrowIfCancellationRequested();
  517. +            declarationsListener.NewDeclaration += declarationsListener_NewDeclaration;
  518. +            declarationsListener.CreateModuleDeclarations();
  519. +
  520. +            token.ThrowIfCancellationRequested();
  521. +            var walker = new ParseTreeWalker();
  522. +            walker.Walk(declarationsListener, tree);
  523. +            declarationsListener.NewDeclaration -= declarationsListener_NewDeclaration;
  524. +
  525. +            _state.ObsoleteCallContexts = obsoleteCallsListener.Contexts.Select(context => new QualifiedContext(qualifiedName, context));
  526. +            _state.ObsoleteLetContexts = obsoleteLetListener.Contexts.Select(context => new QualifiedContext(qualifiedName, context));
  527. +
  528. +            State.SetModuleState(vbComponent, ParserState.Parsed);
  529.          }
  530.  
  531.          public void Resolve(CancellationToken token)
  532. @@ -104,53 +132,6 @@ namespace Rubberduck.Parsing.VBA
  533.              }
  534.          }
  535.  
  536. -        private void ParseInternal(VBComponent vbComponent, CancellationToken token)
  537. -        {
  538. -            _state.ClearDeclarations(vbComponent);
  539. -            State.SetModuleState(vbComponent, ParserState.Parsing);
  540. -
  541. -            var qualifiedName = new QualifiedModuleName(vbComponent);
  542. -            _state.SetModuleComments(vbComponent, ParseComments(qualifiedName));
  543. -
  544. -            var obsoleteCallsListener = new ObsoleteCallStatementListener();
  545. -            var obsoleteLetListener = new ObsoleteLetStatementListener();
  546. -
  547. -            var listeners = new IParseTreeListener[]
  548. -            {
  549. -                obsoleteCallsListener,
  550. -                obsoleteLetListener
  551. -            };
  552. -
  553. -            token.ThrowIfCancellationRequested();
  554. -
  555. -            ITokenStream stream;
  556. -            var code = string.Join("\r\n", vbComponent.CodeModule.Code());
  557. -            var tree = ParseInternal(code, listeners, out stream);
  558. -
  559. -            token.ThrowIfCancellationRequested();
  560. -            _state.AddTokenStream(vbComponent, stream);
  561. -            _state.AddParseTree(vbComponent, tree);
  562. -
  563. -            // cannot locate declarations in one pass *the way it's currently implemented*,
  564. -            // because the context in EnterSubStmt() doesn't *yet* have child nodes when the context enters.
  565. -            // so we need to EnterAmbiguousIdentifier() and evaluate the parent instead - this *might* work.
  566. -            var declarationsListener = new DeclarationSymbolsListener(qualifiedName, Accessibility.Implicit, vbComponent.Type, _state.Comments, token);
  567. -
  568. -            token.ThrowIfCancellationRequested();
  569. -            declarationsListener.NewDeclaration += declarationsListener_NewDeclaration;
  570. -            declarationsListener.CreateModuleDeclarations();
  571. -
  572. -            token.ThrowIfCancellationRequested();
  573. -            var walker = new ParseTreeWalker();
  574. -            walker.Walk(declarationsListener, tree);
  575. -            declarationsListener.NewDeclaration -= declarationsListener_NewDeclaration;
  576. -
  577. -            _state.ObsoleteCallContexts = obsoleteCallsListener.Contexts.Select(context => new QualifiedContext(qualifiedName, context));
  578. -            _state.ObsoleteLetContexts = obsoleteLetListener.Contexts.Select(context => new QualifiedContext(qualifiedName, context));
  579. -
  580. -            State.SetModuleState(vbComponent, ParserState.Parsed);
  581. -        }
  582. -
  583.          private IParseTree ParseInternal(string code, IEnumerable<IParseTreeListener> listeners, out ITokenStream outStream)
  584.          {
  585.              var input = new AntlrInputStream(code);
  586. diff --git a/Rubberduck.Parsing/VBA/RubberduckParserState.cs b/Rubberduck.Parsing/VBA/RubberduckParserState.cs
  587. index 4f9ccaf..e648c90 100644
  588. --- a/Rubberduck.Parsing/VBA/RubberduckParserState.cs
  589. +++ b/Rubberduck.Parsing/VBA/RubberduckParserState.cs
  590. @@ -1,7 +1,9 @@
  591.  using System;
  592.  using System.Collections.Concurrent;
  593.  using System.Collections.Generic;
  594. +using System.Diagnostics;
  595.  using System.Linq;
  596. +using System.Threading;
  597.  using Antlr4.Runtime;
  598.  using Antlr4.Runtime.Tree;
  599.  using Microsoft.Vbe.Interop;
  600. @@ -45,14 +47,20 @@ namespace Rubberduck.Parsing.VBA
  601.              _moduleStates[component] = state;
  602.              _moduleExceptions[component] = parserError;
  603.  
  604. -            Status = _moduleStates.Values.Any(value => value == ParserState.Error)
  605. -                ? ParserState.Error
  606. -                : _moduleStates.Values.Any(value => value == ParserState.Parsing)
  607. -                    ? ParserState.Parsing
  608. -                    : _moduleStates.Values.Any(value => value == ParserState.Resolving)
  609. -                        ? ParserState.Resolving
  610. -                        : ParserState.Ready;
  611. +            var states = _moduleStates.Values.GroupBy(x => x)
  612. +                .ToDictionary(x => x.Key, x => x.Count());
  613.  
  614. +            foreach (var x in new[] {ParserState.Error, ParserState.Parsing, ParserState.Resolving})
  615. +            {
  616. +                int count;
  617. +                if (states.TryGetValue(x, out count) && count > 0)
  618. +                {
  619. +                    Status = x;
  620. +                    return;
  621. +                }
  622. +            }
  623. +
  624. +            Status = ParserState.Ready;
  625.          }
  626.  
  627.          public ParserState GetModuleState(VBComponent component)
  628. @@ -61,7 +69,23 @@ namespace Rubberduck.Parsing.VBA
  629.          }
  630.  
  631.          private ParserState _status;
  632. -        public ParserState Status { get { return _status; } private set { if(_status != value) {_status = value; OnStateChanged();} } }
  633. +
  634. +        public ParserState Status
  635. +        {
  636. +            get
  637. +            {
  638. +                return _status;
  639. +            }
  640. +
  641. +            private set
  642. +            {
  643. +                if (_status != value)
  644. +                {
  645. +                    _status = value;
  646. +                    OnStateChanged();
  647. +                }
  648. +            }
  649. +        }
  650.  
  651.          private IEnumerable<QualifiedContext> _obsoleteCallContexts = new List<QualifiedContext>();
  652.  
  653. @@ -122,17 +146,27 @@ namespace Rubberduck.Parsing.VBA
  654.              }
  655.          }
  656.  
  657. -        public void ClearDeclarations(VBComponent component)
  658. +        public void ClearDeclarations(VBComponent component, CancellationToken token)
  659.          {
  660. -            var declarations = _declarations.Keys.Where(k =>
  661. -                k.QualifiedName.QualifiedModuleName.Project == component.Collection.Parent
  662. -                && k.ComponentName == component.Name);
  663. +            var sw = Stopwatch.StartNew();
  664. +
  665. +            var declarations = _declarations.Keys.AsParallel()
  666. +                .WithCancellation(token)
  667. +                .Where(k =>
  668. +                    k.QualifiedName.QualifiedModuleName.Project == component.Collection.Parent
  669. +                    && k.ComponentName == component.Name)
  670. +                .ToArray();
  671.  
  672.              foreach (var declaration in declarations)
  673.              {
  674. +                token.ThrowIfCancellationRequested();
  675. +
  676.                  ResolutionState state;
  677.                  _declarations.TryRemove(declaration, out state);
  678.              }
  679. +
  680. +            sw.Stop();
  681. +            Debug.WriteLine($"{sw.ElapsedMilliseconds}ms");
  682.          }
  683.  
  684.          public void AddTokenStream(VBComponent component, ITokenStream stream)
Advertisement
Add Comment
Please, Sign In to add comment