{"action":"created","issue":{"url":"https://api.github.com/repos/retailcoder/Rubberduck/issues/554","labels_url":"https://api.github.com/repos/retailcoder/Rubberduck/issues/554/labels{/name}","comments_url":"https://api.github.com/repos/retailcoder/Rubberduck/issues/554/comments","events_url":"https://api.github.com/repos/retailcoder/Rubberduck/issues/554/events","html_url":"https://github.com/retailcoder/Rubberduck/issues/554","id":80169706,"number":554,"title":"Find a way to cache identifier references","user":{"login":"retailcoder","id":5751684,"avatar_url":"https://avatars.githubusercontent.com/u/5751684?v=3","gravatar_id":"","url":"https://api.github.com/users/retailcoder","html_url":"https://github.com/retailcoder","followers_url":"https://api.github.com/users/retailcoder/followers","following_url":"https://api.github.com/users/retailcoder/following{/other_user}","gists_url":"https://api.github.com/users/retailcoder/gists{/gist_id}","starred_url":"https://api.github.com/users/retailcoder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/retailcoder/subscriptions","organizations_url":"https://api.github.com/users/retailcoder/orgs","repos_url":"https://api.github.com/users/retailcoder/repos","events_url":"https://api.github.com/users/retailcoder/events{/privacy}","received_events_url":"https://api.github.com/users/retailcoder/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/retailcoder/Rubberduck/labels/code-parsing","name":"code-parsing","color":"DDDDDD"},{"url":"https://api.github.com/repos/retailcoder/Rubberduck/labels/discussion","name":"discussion","color":"FEFEFE"},{"url":"https://api.github.com/repos/retailcoder/Rubberduck/labels/enhancement","name":"enhancement","color":"FEFEFE"},{"url":"https://api.github.com/repos/retailcoder/Rubberduck/labels/performance","name":"performance","color":"DEDEDE"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-05-24T13:57:38Z","updated_at":"2015-05-24T14:57:49Z","closed_at":null,"body":"We are currently caching ANTLR parse trees, which enables us to avoid re-parsing modules that haven't been modified since the last parse.. but we're still walking every parse tree to resolve identifier references.\r\n\r\nThere's an opportunity for improving performance here.\r\n\r\nThe challenge here is that we're caching `VBComponentParseResult` instances, but the identifier resolution works off a `VBProjectParseResult`. We need to figure out a way to rework the internals of the `RubberduckParser` class so that we don't systematically walk the parse trees every time the parser issues a `VBProjectParseResult`.\r\n\r\n---\r\n\r\nCurrent algorithm goes like this:\r\n\r\n - `VBProjectParseResult Parse(VBProject project, object owner = null)` gets called by a feature requesting a parse result for the active project.\r\n - If the `owner` isn't `null`, raise an event to indicate parsing has started.\r\n - If the `project` is protected, return an empty `VBProjectParseResult`.\r\n - For each module in the `project`, add a `VBComponentParseResult`:\r\n   - If there's a cached parse tree for the `QualifiedModuleName`, return the cached result; if the module was modified since the last parse, the cache will not have an entry for it.\r\n   - Get the module's content, parse it and wrap the parse tree into a new `VBComponentParseResult`\r\n   - Add or update the cache entry for that result.\r\n   - Return the result\r\n - Create a new `VBProjectParseResult`, add all `VBComponentParseResult` instances to it.\r\n - Identify all declarations\r\n - Resolve all identifier usages\r\n\r\nIt seems the declarations could be packaged with the `VBComponentParseResult` and cached along with the parse tree - that makes 1 less traversal, but not the most expensive one.\r\n\r\nLet's discuss what the possibilities are here."},"comment":{"url":"https://api.github.com/repos/retailcoder/Rubberduck/issues/comments/105022749","html_url":"https://github.com/retailcoder/Rubberduck/issues/554#issuecomment-105022749","issue_url":"https://api.github.com/repos/retailcoder/Rubberduck/issues/554","id":105022749,"user":{"login":"retailcoder","id":5751684,"avatar_url":"https://avatars.githubusercontent.com/u/5751684?v=3","gravatar_id":"","url":"https://api.github.com/users/retailcoder","html_url":"https://github.com/retailcoder","followers_url":"https://api.github.com/users/retailcoder/followers","following_url":"https://api.github.com/users/retailcoder/following{/other_user}","gists_url":"https://api.github.com/users/retailcoder/gists{/gist_id}","starred_url":"https://api.github.com/users/retailcoder/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/retailcoder/subscriptions","organizations_url":"https://api.github.com/users/retailcoder/orgs","repos_url":"https://api.github.com/users/retailcoder/repos","events_url":"https://api.github.com/users/retailcoder/events{/privacy}","received_events_url":"https://api.github.com/users/retailcoder/received_events","type":"User","site_admin":false},"created_at":"2015-05-24T14:57:49Z","updated_at":"2015-05-24T14:57:49Z","body":"^^ this commit prevents walking the parse trees again when every parse result is fetched from cache, so we don't re-resolve identifier references if nothing has changed.\r\n\r\nHowever if a single character is added to one of the modules, everything is resolved again. Not bad, but could be better I think."}}