{"action":"created","comment":{"url":"https://api.github.com/repos/Workiva/w_module/pulls/comments/49234373","id":49234373,"diff_hunk":"@@ -0,0 +1,224 @@\n+library w_module.src.transformer.utils;\n+\n+import 'dart:convert';\n+import 'dart:mirrors' as mirrors;\n+\n+import 'package:analyzer/analyzer.dart';\n+import 'package:barback/barback.dart';\n+import 'package:path/path.dart' as path;\n+import 'package:source_span/source_span.dart';\n+\n+// TODO: Extract these utilities to a common library (taken from web_sin_dart)\n+\n+class Replacement {\n+  final SourceSpan span;\n+  final String newText;\n+\n+  Replacement(this.span, this.newText);\n+\n+  @override\n+  String toString() => 'Replacement (span: $span, newText: $newText)';\n+}\n+\n+class TransformedSourceFile {\n+  final List<Replacement> _replacements = [];\n+\n+  final SourceFile sourceFile;\n+\n+  TransformedSourceFile(this.sourceFile);\n+\n+  bool get isModified => _replacements.isNotEmpty;\n+\n+  void insert(SourceLocation location, String text) {\n+    _replacements.add(\n+        new Replacement(location.pointSpan(), text)\n+    );\n+  }\n+\n+  void replace(SourceSpan span, String text) {\n+    _replacements.add(\n+        new Replacement(span, text)\n+    );\n+  }\n+\n+  void iterateReplacements({onUnmodified(String string), onRemoval(String string), onAddition(String string)}) {\n+    _replacements.sort((r1, r2) => r1.span.compareTo(r2.span));\n+\n+    var lastEdge = 0;\n+    for (Replacement replacement in _replacements) {\n+      if (replacement.span.start.offset < lastEdge) {\n+        throw 'Overlapping replacement $replacement in replacements $_replacements.';\n+      }\n+\n+      var unmodifiedText = sourceFile.getText(lastEdge, replacement.span.start.offset);\n+      var removalText = replacement.span.text;\n+      var additionText = replacement.newText;\n+\n+      if (onUnmodified != null && unmodifiedText.isNotEmpty) {\n+        onUnmodified(unmodifiedText);\n+      }\n+      if (onRemoval != null && removalText.isNotEmpty) {\n+        onRemoval(removalText);\n+      }\n+      if (onAddition != null && additionText.isNotEmpty) {\n+        onAddition(additionText);\n+      }\n+\n+      lastEdge = replacement.span.end.offset;\n+    }\n+\n+    var unmodifiedText = sourceFile.getText(lastEdge);\n+    if (onUnmodified != null && unmodifiedText != null) {\n+      onUnmodified(unmodifiedText);\n+    }\n+  }\n+\n+  String getTransformedText() {\n+    StringBuffer transformedSource = new StringBuffer();\n+\n+    iterateReplacements(\n+        onUnmodified: transformedSource.write,\n+        onAddition: transformedSource.write\n+    );\n+\n+    return transformedSource.toString();\n+  }\n+\n+  String getHtmlDiff() {\n+    const HtmlEscape elementEscaper = const HtmlEscape(HtmlEscapeMode.ELEMENT);\n+    const HtmlEscape attrEscaper = const HtmlEscape(HtmlEscapeMode.ATTRIBUTE);\n+\n+    StringBuffer diff = new StringBuffer();\n+\n+    void writeDiff(String source, String className) {\n+      diff.write('<span class=\"$className\">');\n+      diff.write(elementEscaper.convert(source));\n+      diff.write('</span>');\n+    }\n+\n+    iterateReplacements(\n+        onUnmodified: (source) => writeDiff(source, 'diff-unmodified'),\n+        onRemoval: (source) => writeDiff(source, 'diff-removal'),\n+        onAddition: (source) => writeDiff(source, 'diff-addition')\n+    );\n+\n+    return '''\n+        <!DOCTYPE html>\n+        <html>\n+        <head>\n+          <title>web_skin_dart Transformer Diff - ${attrEscaper.convert(sourceFile.url.path)}</title>","path":"lib/src/transformer/utils.dart","position":109,"original_position":109,"commit_id":"29427e64792cd3facc54d879384c511dbdd7a91b","original_commit_id":"29427e64792cd3facc54d879384c511dbdd7a91b","user":{"login":"greglittlefield-wf","id":1713967,"avatar_url":"https://avatars.githubusercontent.com/u/1713967?v=3","gravatar_id":"","url":"https://api.github.com/users/greglittlefield-wf","html_url":"https://github.com/greglittlefield-wf","followers_url":"https://api.github.com/users/greglittlefield-wf/followers","following_url":"https://api.github.com/users/greglittlefield-wf/following{/other_user}","gists_url":"https://api.github.com/users/greglittlefield-wf/gists{/gist_id}","starred_url":"https://api.github.com/users/greglittlefield-wf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/greglittlefield-wf/subscriptions","organizations_url":"https://api.github.com/users/greglittlefield-wf/orgs","repos_url":"https://api.github.com/users/greglittlefield-wf/repos","events_url":"https://api.github.com/users/greglittlefield-wf/events{/privacy}","received_events_url":"https://api.github.com/users/greglittlefield-wf/received_events","type":"User","site_admin":false},"body":"Works for me. :)","created_at":"2016-01-08T20:29:26Z","updated_at":"2016-01-08T20:29:26Z","html_url":"https://github.com/Workiva/w_module/pull/40#discussion_r49234373","pull_request_url":"https://api.github.com/repos/Workiva/w_module/pulls/40","_links":{"self":{"href":"https://api.github.com/repos/Workiva/w_module/pulls/comments/49234373"},"html":{"href":"https://github.com/Workiva/w_module/pull/40#discussion_r49234373"},"pull_request":{"href":"https://api.github.com/repos/Workiva/w_module/pulls/40"}}},"pull_request":{"url":"https://api.github.com/repos/Workiva/w_module/pulls/40","id":52698117,"html_url":"https://github.com/Workiva/w_module/pull/40","diff_url":"https://github.com/Workiva/w_module/pull/40.diff","patch_url":"https://github.com/Workiva/w_module/pull/40.patch","issue_url":"https://api.github.com/repos/Workiva/w_module/issues/40","number":40,"state":"open","locked":false,"title":"Add DeferredModule transformer.","user":{"login":"evanweible-wf","id":1738457,"avatar_url":"https://avatars.githubusercontent.com/u/1738457?v=3","gravatar_id":"","url":"https://api.github.com/users/evanweible-wf","html_url":"https://github.com/evanweible-wf","followers_url":"https://api.github.com/users/evanweible-wf/followers","following_url":"https://api.github.com/users/evanweible-wf/following{/other_user}","gists_url":"https://api.github.com/users/evanweible-wf/gists{/gist_id}","starred_url":"https://api.github.com/users/evanweible-wf/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/evanweible-wf/subscriptions","organizations_url":"https://api.github.com/users/evanweible-wf/orgs","repos_url":"https://api.github.com/users/evanweible-wf/repos","events_url":"https://api.github.com/users/evanweible-wf/events{/privacy}","received_events_url":"https://api.github.com/users/evanweible-wf/received_events","type":"User","site_admin":false},"body":"## Issue\r\n- Need a way to create deferred versions of modules with as little effort as possible and without the need to recreate the deferred module loading logic in the module lifecycle.\r\n\r\n## Changes\r\n**Source:**\r\n- Use a pub transformer to generate the deferred module implementation.\r\n- Generates getters for API, Components, and Events that throw if the module hasn't been loaded and proxy to the real module once it has been loaded\r\n- Generates constructor bodies that store the args and proxy them to the real constructor when called\r\n- Generates the module lifecycle implementations that loads the deferred library during the \"onLoad\" event\r\n\r\n**Tests:**\r\n- None yet, coming soon.\r\n\r\n## Areas of Regression\r\n- n/a\r\n\r\n## Testing\r\n- TBD\r\n\r\n## TODO\r\n- [ ] Documentation\r\n- [ ] More examples\r\n- [ ] Create a `DeferredModule` class to inherit from that expects a `loadDeferred` method implementation (replaces the \"string\" reference to the deferred library prefix used in the `DeferredModule` annotation)\r\n- [ ] Add more warnings if there are discrepancies between the real module and the deferred version\r\n\r\n## Code Review\r\n@greglittlefield-wf \r\n@trentgrover-wf\r\n@maxwellpeterson-wf \r\n@dustinlessard-wf\r\n@jayudey-wf ","created_at":"2015-12-04T17:35:02Z","updated_at":"2016-01-08T20:29:26Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1d2e2c3a9674233dea90e5344c731ce0f76595ee","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/Workiva/w_module/pulls/40/commits","review_comments_url":"https://api.github.com/repos/Workiva/w_module/pulls/40/comments","review_comment_url":"https://api.github.com/repos/Workiva/w_module/pulls/comments{/number}","comments_url":"https://api.github.com/repos/Workiva/w_module/issues/40/comments","statuses_url":"https://api.github.com/repos/Workiva/w_module/statuses/29427e64792cd3facc54d879384c511dbdd7a91b","head":{"label":"Workiva:deferred-module-transformer","ref":"deferred-module-transformer","sha":"29427e64792cd3facc54d879384c511dbdd7a91b","user":{"login":"Workiva","id":1087529,"avatar_url":"https://avatars.githubusercontent.com/u/1087529?v=3","gravatar_id":"","url":"https://api.github.com/users/Workiva","html_url":"https://github.com/Workiva","followers_url":"https://api.github.com/users/Workiva/followers","following_url":"https://api.github.com/users/Workiva/following{/other_user}","gists_url":"https://api.github.com/users/Workiva/gists{/gist_id}","starred_url":"https://api.github.com/users/Workiva/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Workiva/subscriptions","organizations_url":"https://api.github.com/users/Workiva/orgs","repos_url":"https://api.github.com/users/Workiva/repos","events_url":"https://api.github.com/users/Workiva/events{/privacy}","received_events_url":"https://api.github.com/users/Workiva/received_events","type":"Organization","site_admin":false},"repo":{"id":36083980,"name":"w_module","full_name":"Workiva/w_module","owner":{"login":"Workiva","id":1087529,"avatar_url":"https://avatars.githubusercontent.com/u/1087529?v=3","gravatar_id":"","url":"https://api.github.com/users/Workiva","html_url":"https://github.com/Workiva","followers_url":"https://api.github.com/users/Workiva/followers","following_url":"https://api.github.com/users/Workiva/following{/other_user}","gists_url":"https://api.github.com/users/Workiva/gists{/gist_id}","starred_url":"https://api.github.com/users/Workiva/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Workiva/subscriptions","organizations_url":"https://api.github.com/users/Workiva/orgs","repos_url":"https://api.github.com/users/Workiva/repos","events_url":"https://api.github.com/users/Workiva/events{/privacy}","received_events_url":"https://api.github.com/users/Workiva/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Workiva/w_module","description":"","fork":false,"url":"https://api.github.com/repos/Workiva/w_module","forks_url":"https://api.github.com/repos/Workiva/w_module/forks","keys_url":"https://api.github.com/repos/Workiva/w_module/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Workiva/w_module/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Workiva/w_module/teams","hooks_url":"https://api.github.com/repos/Workiva/w_module/hooks","issue_events_url":"https://api.github.com/repos/Workiva/w_module/issues/events{/number}","events_url":"https://api.github.com/repos/Workiva/w_module/events","assignees_url":"https://api.github.com/repos/Workiva/w_module/assignees{/user}","branches_url":"https://api.github.com/repos/Workiva/w_module/branches{/branch}","tags_url":"https://api.github.com/repos/Workiva/w_module/tags","blobs_url":"https://api.github.com/repos/Workiva/w_module/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Workiva/w_module/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Workiva/w_module/git/refs{/sha}","trees_url":"https://api.github.com/repos/Workiva/w_module/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Workiva/w_module/statuses/{sha}","languages_url":"https://api.github.com/repos/Workiva/w_module/languages","stargazers_url":"https://api.github.com/repos/Workiva/w_module/stargazers","contributors_url":"https://api.github.com/repos/Workiva/w_module/contributors","subscribers_url":"https://api.github.com/repos/Workiva/w_module/subscribers","subscription_url":"https://api.github.com/repos/Workiva/w_module/subscription","commits_url":"https://api.github.com/repos/Workiva/w_module/commits{/sha}","git_commits_url":"https://api.github.com/repos/Workiva/w_module/git/commits{/sha}","comments_url":"https://api.github.com/repos/Workiva/w_module/comments{/number}","issue_comment_url":"https://api.github.com/repos/Workiva/w_module/issues/comments{/number}","contents_url":"https://api.github.com/repos/Workiva/w_module/contents/{+path}","compare_url":"https://api.github.com/repos/Workiva/w_module/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Workiva/w_module/merges","archive_url":"https://api.github.com/repos/Workiva/w_module/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Workiva/w_module/downloads","issues_url":"https://api.github.com/repos/Workiva/w_module/issues{/number}","pulls_url":"https://api.github.com/repos/Workiva/w_module/pulls{/number}","milestones_url":"https://api.github.com/repos/Workiva/w_module/milestones{/number}","notifications_url":"https://api.github.com/repos/Workiva/w_module/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Workiva/w_module/labels{/name}","releases_url":"https://api.github.com/repos/Workiva/w_module/releases{/id}","created_at":"2015-05-22T16:51:11Z","updated_at":"2015-12-14T03:12:27Z","pushed_at":"2016-01-04T17:16:26Z","git_url":"git://github.com/Workiva/w_module.git","ssh_url":"git@github.com:Workiva/w_module.git","clone_url":"https://github.com/Workiva/w_module.git","svn_url":"https://github.com/Workiva/w_module","homepage":null,"size":308,"stargazers_count":6,"watchers_count":6,"language":"Dart","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":6,"forks":1,"open_issues":6,"watchers":6,"default_branch":"master"}},"base":{"label":"Workiva:master","ref":"master","sha":"6594d5253d0bc2edf5be73681c27cf05d9e99567","user":{"login":"Workiva","id":1087529,"avatar_url":"https://avatars.githubusercontent.com/u/1087529?v=3","gravatar_id":"","url":"https://api.github.com/users/Workiva","html_url":"https://github.com/Workiva","followers_url":"https://api.github.com/users/Workiva/followers","following_url":"https://api.github.com/users/Workiva/following{/other_user}","gists_url":"https://api.github.com/users/Workiva/gists{/gist_id}","starred_url":"https://api.github.com/users/Workiva/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Workiva/subscriptions","organizations_url":"https://api.github.com/users/Workiva/orgs","repos_url":"https://api.github.com/users/Workiva/repos","events_url":"https://api.github.com/users/Workiva/events{/privacy}","received_events_url":"https://api.github.com/users/Workiva/received_events","type":"Organization","site_admin":false},"repo":{"id":36083980,"name":"w_module","full_name":"Workiva/w_module","owner":{"login":"Workiva","id":1087529,"avatar_url":"https://avatars.githubusercontent.com/u/1087529?v=3","gravatar_id":"","url":"https://api.github.com/users/Workiva","html_url":"https://github.com/Workiva","followers_url":"https://api.github.com/users/Workiva/followers","following_url":"https://api.github.com/users/Workiva/following{/other_user}","gists_url":"https://api.github.com/users/Workiva/gists{/gist_id}","starred_url":"https://api.github.com/users/Workiva/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Workiva/subscriptions","organizations_url":"https://api.github.com/users/Workiva/orgs","repos_url":"https://api.github.com/users/Workiva/repos","events_url":"https://api.github.com/users/Workiva/events{/privacy}","received_events_url":"https://api.github.com/users/Workiva/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/Workiva/w_module","description":"","fork":false,"url":"https://api.github.com/repos/Workiva/w_module","forks_url":"https://api.github.com/repos/Workiva/w_module/forks","keys_url":"https://api.github.com/repos/Workiva/w_module/keys{/key_id}","collaborators_url":"https://api.github.com/repos/Workiva/w_module/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/Workiva/w_module/teams","hooks_url":"https://api.github.com/repos/Workiva/w_module/hooks","issue_events_url":"https://api.github.com/repos/Workiva/w_module/issues/events{/number}","events_url":"https://api.github.com/repos/Workiva/w_module/events","assignees_url":"https://api.github.com/repos/Workiva/w_module/assignees{/user}","branches_url":"https://api.github.com/repos/Workiva/w_module/branches{/branch}","tags_url":"https://api.github.com/repos/Workiva/w_module/tags","blobs_url":"https://api.github.com/repos/Workiva/w_module/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/Workiva/w_module/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/Workiva/w_module/git/refs{/sha}","trees_url":"https://api.github.com/repos/Workiva/w_module/git/trees{/sha}","statuses_url":"https://api.github.com/repos/Workiva/w_module/statuses/{sha}","languages_url":"https://api.github.com/repos/Workiva/w_module/languages","stargazers_url":"https://api.github.com/repos/Workiva/w_module/stargazers","contributors_url":"https://api.github.com/repos/Workiva/w_module/contributors","subscribers_url":"https://api.github.com/repos/Workiva/w_module/subscribers","subscription_url":"https://api.github.com/repos/Workiva/w_module/subscription","commits_url":"https://api.github.com/repos/Workiva/w_module/commits{/sha}","git_commits_url":"https://api.github.com/repos/Workiva/w_module/git/commits{/sha}","comments_url":"https://api.github.com/repos/Workiva/w_module/comments{/number}","issue_comment_url":"https://api.github.com/repos/Workiva/w_module/issues/comments{/number}","contents_url":"https://api.github.com/repos/Workiva/w_module/contents/{+path}","compare_url":"https://api.github.com/repos/Workiva/w_module/compare/{base}...{head}","merges_url":"https://api.github.com/repos/Workiva/w_module/merges","archive_url":"https://api.github.com/repos/Workiva/w_module/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/Workiva/w_module/downloads","issues_url":"https://api.github.com/repos/Workiva/w_module/issues{/number}","pulls_url":"https://api.github.com/repos/Workiva/w_module/pulls{/number}","milestones_url":"https://api.github.com/repos/Workiva/w_module/milestones{/number}","notifications_url":"https://api.github.com/repos/Workiva/w_module/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/Workiva/w_module/labels{/name}","releases_url":"https://api.github.com/repos/Workiva/w_module/releases{/id}","created_at":"2015-05-22T16:51:11Z","updated_at":"2015-12-14T03:12:27Z","pushed_at":"2016-01-04T17:16:26Z","git_url":"git://github.com/Workiva/w_module.git","ssh_url":"git@github.com:Workiva/w_module.git","clone_url":"https://github.com/Workiva/w_module.git","svn_url":"https://github.com/Workiva/w_module","homepage":null,"size":308,"stargazers_count":6,"watchers_count":6,"language":"Dart","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":1,"mirror_url":null,"open_issues_count":6,"forks":1,"open_issues":6,"watchers":6,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/Workiva/w_module/pulls/40"},"html":{"href":"https://github.com/Workiva/w_module/pull/40"},"issue":{"href":"https://api.github.com/repos/Workiva/w_module/issues/40"},"comments":{"href":"https://api.github.com/repos/Workiva/w_module/issues/40/comments"},"review_comments":{"href":"https://api.github.com/repos/Workiva/w_module/pulls/40/comments"},"review_comment":{"href":"https://api.github.com/repos/Workiva/w_module/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/Workiva/w_module/pulls/40/commits"},"statuses":{"href":"https://api.github.com/repos/Workiva/w_module/statuses/29427e64792cd3facc54d879384c511dbdd7a91b"}}}}