{"action":"created","comment":{"url":"https://api.github.com/repos/apple/swift-package-manager/pulls/comments/54353254","id":54353254,"diff_hunk":"@@ -0,0 +1,112 @@\n+/*\n+ This source file is part of the Swift.org open source project\n+ \n+ Copyright 2015 - 2016 Apple Inc. and the Swift project authors\n+ Licensed under Apache License v2.0 with Runtime Library Exception\n+ \n+ See http://swift.org/LICENSE.txt for license information\n+ See http://swift.org/CONTRIBUTORS.txt for Swift project authors\n+ */\n+\n+import Utility\n+import PackageType\n+\n+struct TestClassMetadata {\n+    let name: String\n+    let testNames: [String]\n+}\n+\n+struct ModuleTestMetadata {\n+    let module: TestModule\n+    let testManifestPath: String\n+    let dependencies: [String]\n+    let classes: [TestClassMetadata]\n+}\n+\n+protocol TestMetadataParser {\n+    func parseTestClasses(testFilePath: String) throws -> [TestClassMetadata]?\n+}\n+\n+//up for grabs\n+//struct ASTTestMetadataParser: TestMetadataParser {\n+//    \n+//\n+//}\n+\n+struct StringTestMetadataParser: TestMetadataParser {\n+    \n+    /// Based on the absolute path passed in parses test class metadata\n+    /// Returns array because there might be more test classes in one file\n+    func parseTestClasses(testFilePath: String) throws -> [TestClassMetadata]? {\n+        \n+        guard let lines = try? File(path: testFilePath).enumerate() else { return nil }\n+        \n+        var classes = [TestClassMetadata]()\n+        func finishClass(className: String?, _ testNames: [String]) {\n+            if let className = className where testNames.count > 0 {\n+                let testClass = TestClassMetadata(name: className, testNames: testNames)\n+                classes.append(testClass)\n+            }\n+        }\n+        \n+        //parse lines one by one, no need to load the whole into memory\n+        var className: String? = nil\n+        var testNames = [String]()\n+        while true {\n+            \n+            guard let line = lines.next() else {\n+                //EOF, no more classes\n+                finishClass(className, testNames)\n+                testNames = []\n+                return classes.nilIfEmpty()\n+            }\n+            \n+            //look for a class name\n+            if let newClassName = parseClassName(line) {\n+                //found class name, finish old class and start new\n+                finishClass(className, testNames)\n+                className = newClassName\n+                testNames = []\n+            }\n+            \n+            //look for a test case\n+            if let testName = parseTestName(line) {\n+                //found another test name\n+                testNames.append(testName)\n+            }\n+        }\n+    }\n+    \n+    func parseClassName(line: String) -> String? {\n+        var comps = line.splitWithCharactersInString(\":\\r\\t\\n \").filter { !$0.isEmpty }\n+        guard comps.count >= 2 else { return nil }\n+        //see if this line is a candidate\n+        guard Set(comps).contains(\"class\") else { return nil }\n+        while true {\n+            let allowedFirst = Set([\"private\", \"public\", \"internal\", \"final\"])","path":"Sources/Build/TestMetadataParser.swift","position":85,"original_position":86,"commit_id":"500911d87acd37cce4b4846d8c5b76c40068ba6c","original_commit_id":"734530c18c5277961437fa41f71f1a5b29cb52a9","user":{"login":"modocache","id":552921,"avatar_url":"https://avatars.githubusercontent.com/u/552921?v=3","gravatar_id":"","url":"https://api.github.com/users/modocache","html_url":"https://github.com/modocache","followers_url":"https://api.github.com/users/modocache/followers","following_url":"https://api.github.com/users/modocache/following{/other_user}","gists_url":"https://api.github.com/users/modocache/gists{/gist_id}","starred_url":"https://api.github.com/users/modocache/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/modocache/subscriptions","organizations_url":"https://api.github.com/users/modocache/orgs","repos_url":"https://api.github.com/users/modocache/repos","events_url":"https://api.github.com/users/modocache/events{/privacy}","received_events_url":"https://api.github.com/users/modocache/received_events","type":"User","site_admin":false},"body":"(Whoops! Updated my comment to `private class`. Thanks for pointing that out.)\r\n\r\nMy vote is for a very specific error, although I agree with your concerns about how to implement it. I think end users would be confused if `swift test` failed with a build error. It'd be nicer if we failed with an error such as: \"class Foo is marked private. Private test case classes are not supported. Please mark Foo as internal or public.\"\r\n\r\n","created_at":"2016-02-28T17:38:23Z","updated_at":"2016-02-28T17:38:23Z","html_url":"https://github.com/apple/swift-package-manager/pull/156#discussion_r54353254","pull_request_url":"https://api.github.com/repos/apple/swift-package-manager/pulls/156","_links":{"self":{"href":"https://api.github.com/repos/apple/swift-package-manager/pulls/comments/54353254"},"html":{"href":"https://github.com/apple/swift-package-manager/pull/156#discussion_r54353254"},"pull_request":{"href":"https://api.github.com/repos/apple/swift-package-manager/pulls/156"}}},"pull_request":{"url":"https://api.github.com/repos/apple/swift-package-manager/pulls/156","id":60970139,"html_url":"https://github.com/apple/swift-package-manager/pull/156","diff_url":"https://github.com/apple/swift-package-manager/pull/156.diff","patch_url":"https://github.com/apple/swift-package-manager/pull/156.patch","issue_url":"https://api.github.com/repos/apple/swift-package-manager/issues/156","number":156,"state":"open","locked":false,"title":"[WIP] Automatic Linux test manifest generation","user":{"login":"czechboy0","id":2182121,"avatar_url":"https://avatars.githubusercontent.com/u/2182121?v=3","gravatar_id":"","url":"https://api.github.com/users/czechboy0","html_url":"https://github.com/czechboy0","followers_url":"https://api.github.com/users/czechboy0/followers","following_url":"https://api.github.com/users/czechboy0/following{/other_user}","gists_url":"https://api.github.com/users/czechboy0/gists{/gist_id}","starred_url":"https://api.github.com/users/czechboy0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/czechboy0/subscriptions","organizations_url":"https://api.github.com/users/czechboy0/orgs","repos_url":"https://api.github.com/users/czechboy0/repos","events_url":"https://api.github.com/users/czechboy0/events{/privacy}","received_events_url":"https://api.github.com/users/czechboy0/received_events","type":"User","site_admin":false},"body":"https://bugs.swift.org/browse/SR-710\r\n\r\nThis is first stab at automatically generating Linux test manifests. Generation seems to be working correctly, but I haven't written any tests yet and a couple of edge cases need handling. I wanted to present this early to get feedback.\r\n\r\n- Please note that at the moment I'm using naive string-based parsing of the test classes to find test cases. Even though it's simple, I haven't yet found a case which it can't handle. Still, AST-based discovery is the long term goal here.\r\n\r\n- Note that the generation only happens on Linux, so if you want to test it out on a Mac just comment out the ifdef in `describe()` down where LinuxMain is mentioned.\r\n\r\nDONE\r\n- [x] in build phase automatically generates/updates the `LinuxMain.swift` file, and it newly generates a `LinuxTestManifest.swift` file in each test module's folder. The user's test files are untouched, which I like better than the current practice of having the ifdef'd Linux headers.\r\n- [x] all test classes in LinuxMain are now scoped by their module, so there's no issue when two modules have the same test class name\r\n- [x] swiftpm's own tests are getting generated correctly, so this PR removes the manual Linux XCTestCaseProvider extensions and Linux main. And if we decide to keep the generated files as part of user's source, we will just check the new ones in.\r\n- [x] LinuxTestManifest.swift for each module are now correctly added to the module's sources. I had to add a function on `Module` to allow for adding sources after creation with an array of absolute paths. \r\n\r\nTODO with Questions\r\n- [ ] where do we want to keep these files? At the moment I'm generating them next to the user's source files in Tests, but it feels like something that should be generated in `.build`. Thoughts?\r\n- [ ] look into using an actual AST parser (e.g. `swiftc -dump-ast`)\r\n- [ ] How should we handle projects that already have these files created manually? For now I'm assuming they're not there, but I'd prefer to warn/error out if we detect the Linux-specific manifests. A less aggresive solution would be to ignore test files which already have a header of this sorts (extension of XCTestCaseProvider). The current/unhandled behavior is that users get \"illegal redeclaration of allTests...\" because the same extension has been 1. manually created by the user, 2. generated.\r\n\r\nAs you can see, I have many questions that I need feedback on before I push this any further.\r\n\r\nTagging @mxcl because we already talked about this on Twitter.","created_at":"2016-02-27T23:41:06Z","updated_at":"2016-02-28T17:38:23Z","closed_at":null,"merged_at":null,"merge_commit_sha":"71e58a19ede80d0b84e9503e8deaded2769ebbbc","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/apple/swift-package-manager/pulls/156/commits","review_comments_url":"https://api.github.com/repos/apple/swift-package-manager/pulls/156/comments","review_comment_url":"https://api.github.com/repos/apple/swift-package-manager/pulls/comments{/number}","comments_url":"https://api.github.com/repos/apple/swift-package-manager/issues/156/comments","statuses_url":"https://api.github.com/repos/apple/swift-package-manager/statuses/500911d87acd37cce4b4846d8c5b76c40068ba6c","head":{"label":"czechboy0:hd/autogenerate_test_manifest","ref":"hd/autogenerate_test_manifest","sha":"500911d87acd37cce4b4846d8c5b76c40068ba6c","user":{"login":"czechboy0","id":2182121,"avatar_url":"https://avatars.githubusercontent.com/u/2182121?v=3","gravatar_id":"","url":"https://api.github.com/users/czechboy0","html_url":"https://github.com/czechboy0","followers_url":"https://api.github.com/users/czechboy0/followers","following_url":"https://api.github.com/users/czechboy0/following{/other_user}","gists_url":"https://api.github.com/users/czechboy0/gists{/gist_id}","starred_url":"https://api.github.com/users/czechboy0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/czechboy0/subscriptions","organizations_url":"https://api.github.com/users/czechboy0/orgs","repos_url":"https://api.github.com/users/czechboy0/repos","events_url":"https://api.github.com/users/czechboy0/events{/privacy}","received_events_url":"https://api.github.com/users/czechboy0/received_events","type":"User","site_admin":false},"repo":{"id":52691917,"name":"swift-package-manager","full_name":"czechboy0/swift-package-manager","owner":{"login":"czechboy0","id":2182121,"avatar_url":"https://avatars.githubusercontent.com/u/2182121?v=3","gravatar_id":"","url":"https://api.github.com/users/czechboy0","html_url":"https://github.com/czechboy0","followers_url":"https://api.github.com/users/czechboy0/followers","following_url":"https://api.github.com/users/czechboy0/following{/other_user}","gists_url":"https://api.github.com/users/czechboy0/gists{/gist_id}","starred_url":"https://api.github.com/users/czechboy0/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/czechboy0/subscriptions","organizations_url":"https://api.github.com/users/czechboy0/orgs","repos_url":"https://api.github.com/users/czechboy0/repos","events_url":"https://api.github.com/users/czechboy0/events{/privacy}","received_events_url":"https://api.github.com/users/czechboy0/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/czechboy0/swift-package-manager","description":"The Package Manager for the Swift Programming Language","fork":true,"url":"https://api.github.com/repos/czechboy0/swift-package-manager","forks_url":"https://api.github.com/repos/czechboy0/swift-package-manager/forks","keys_url":"https://api.github.com/repos/czechboy0/swift-package-manager/keys{/key_id}","collaborators_url":"https://api.github.com/repos/czechboy0/swift-package-manager/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/czechboy0/swift-package-manager/teams","hooks_url":"https://api.github.com/repos/czechboy0/swift-package-manager/hooks","issue_events_url":"https://api.github.com/repos/czechboy0/swift-package-manager/issues/events{/number}","events_url":"https://api.github.com/repos/czechboy0/swift-package-manager/events","assignees_url":"https://api.github.com/repos/czechboy0/swift-package-manager/assignees{/user}","branches_url":"https://api.github.com/repos/czechboy0/swift-package-manager/branches{/branch}","tags_url":"https://api.github.com/repos/czechboy0/swift-package-manager/tags","blobs_url":"https://api.github.com/repos/czechboy0/swift-package-manager/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/czechboy0/swift-package-manager/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/czechboy0/swift-package-manager/git/refs{/sha}","trees_url":"https://api.github.com/repos/czechboy0/swift-package-manager/git/trees{/sha}","statuses_url":"https://api.github.com/repos/czechboy0/swift-package-manager/statuses/{sha}","languages_url":"https://api.github.com/repos/czechboy0/swift-package-manager/languages","stargazers_url":"https://api.github.com/repos/czechboy0/swift-package-manager/stargazers","contributors_url":"https://api.github.com/repos/czechboy0/swift-package-manager/contributors","subscribers_url":"https://api.github.com/repos/czechboy0/swift-package-manager/subscribers","subscription_url":"https://api.github.com/repos/czechboy0/swift-package-manager/subscription","commits_url":"https://api.github.com/repos/czechboy0/swift-package-manager/commits{/sha}","git_commits_url":"https://api.github.com/repos/czechboy0/swift-package-manager/git/commits{/sha}","comments_url":"https://api.github.com/repos/czechboy0/swift-package-manager/comments{/number}","issue_comment_url":"https://api.github.com/repos/czechboy0/swift-package-manager/issues/comments{/number}","contents_url":"https://api.github.com/repos/czechboy0/swift-package-manager/contents/{+path}","compare_url":"https://api.github.com/repos/czechboy0/swift-package-manager/compare/{base}...{head}","merges_url":"https://api.github.com/repos/czechboy0/swift-package-manager/merges","archive_url":"https://api.github.com/repos/czechboy0/swift-package-manager/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/czechboy0/swift-package-manager/downloads","issues_url":"https://api.github.com/repos/czechboy0/swift-package-manager/issues{/number}","pulls_url":"https://api.github.com/repos/czechboy0/swift-package-manager/pulls{/number}","milestones_url":"https://api.github.com/repos/czechboy0/swift-package-manager/milestones{/number}","notifications_url":"https://api.github.com/repos/czechboy0/swift-package-manager/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/czechboy0/swift-package-manager/labels{/name}","releases_url":"https://api.github.com/repos/czechboy0/swift-package-manager/releases{/id}","deployments_url":"https://api.github.com/repos/czechboy0/swift-package-manager/deployments","created_at":"2016-02-27T22:27:31Z","updated_at":"2016-02-27T22:27:32Z","pushed_at":"2016-02-28T13:04:05Z","git_url":"git://github.com/czechboy0/swift-package-manager.git","ssh_url":"git@github.com:czechboy0/swift-package-manager.git","clone_url":"https://github.com/czechboy0/swift-package-manager.git","svn_url":"https://github.com/czechboy0/swift-package-manager","homepage":"","size":806,"stargazers_count":0,"watchers_count":0,"language":"Swift","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"apple:master","ref":"master","sha":"e83af8bf25457f8a1438f1d9cc46db9b01596bdf","user":{"login":"apple","id":10639145,"avatar_url":"https://avatars.githubusercontent.com/u/10639145?v=3","gravatar_id":"","url":"https://api.github.com/users/apple","html_url":"https://github.com/apple","followers_url":"https://api.github.com/users/apple/followers","following_url":"https://api.github.com/users/apple/following{/other_user}","gists_url":"https://api.github.com/users/apple/gists{/gist_id}","starred_url":"https://api.github.com/users/apple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apple/subscriptions","organizations_url":"https://api.github.com/users/apple/orgs","repos_url":"https://api.github.com/users/apple/repos","events_url":"https://api.github.com/users/apple/events{/privacy}","received_events_url":"https://api.github.com/users/apple/received_events","type":"Organization","site_admin":false},"repo":{"id":44840041,"name":"swift-package-manager","full_name":"apple/swift-package-manager","owner":{"login":"apple","id":10639145,"avatar_url":"https://avatars.githubusercontent.com/u/10639145?v=3","gravatar_id":"","url":"https://api.github.com/users/apple","html_url":"https://github.com/apple","followers_url":"https://api.github.com/users/apple/followers","following_url":"https://api.github.com/users/apple/following{/other_user}","gists_url":"https://api.github.com/users/apple/gists{/gist_id}","starred_url":"https://api.github.com/users/apple/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/apple/subscriptions","organizations_url":"https://api.github.com/users/apple/orgs","repos_url":"https://api.github.com/users/apple/repos","events_url":"https://api.github.com/users/apple/events{/privacy}","received_events_url":"https://api.github.com/users/apple/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/apple/swift-package-manager","description":"The Package Manager for the Swift Programming Language","fork":false,"url":"https://api.github.com/repos/apple/swift-package-manager","forks_url":"https://api.github.com/repos/apple/swift-package-manager/forks","keys_url":"https://api.github.com/repos/apple/swift-package-manager/keys{/key_id}","collaborators_url":"https://api.github.com/repos/apple/swift-package-manager/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/apple/swift-package-manager/teams","hooks_url":"https://api.github.com/repos/apple/swift-package-manager/hooks","issue_events_url":"https://api.github.com/repos/apple/swift-package-manager/issues/events{/number}","events_url":"https://api.github.com/repos/apple/swift-package-manager/events","assignees_url":"https://api.github.com/repos/apple/swift-package-manager/assignees{/user}","branches_url":"https://api.github.com/repos/apple/swift-package-manager/branches{/branch}","tags_url":"https://api.github.com/repos/apple/swift-package-manager/tags","blobs_url":"https://api.github.com/repos/apple/swift-package-manager/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/apple/swift-package-manager/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/apple/swift-package-manager/git/refs{/sha}","trees_url":"https://api.github.com/repos/apple/swift-package-manager/git/trees{/sha}","statuses_url":"https://api.github.com/repos/apple/swift-package-manager/statuses/{sha}","languages_url":"https://api.github.com/repos/apple/swift-package-manager/languages","stargazers_url":"https://api.github.com/repos/apple/swift-package-manager/stargazers","contributors_url":"https://api.github.com/repos/apple/swift-package-manager/contributors","subscribers_url":"https://api.github.com/repos/apple/swift-package-manager/subscribers","subscription_url":"https://api.github.com/repos/apple/swift-package-manager/subscription","commits_url":"https://api.github.com/repos/apple/swift-package-manager/commits{/sha}","git_commits_url":"https://api.github.com/repos/apple/swift-package-manager/git/commits{/sha}","comments_url":"https://api.github.com/repos/apple/swift-package-manager/comments{/number}","issue_comment_url":"https://api.github.com/repos/apple/swift-package-manager/issues/comments{/number}","contents_url":"https://api.github.com/repos/apple/swift-package-manager/contents/{+path}","compare_url":"https://api.github.com/repos/apple/swift-package-manager/compare/{base}...{head}","merges_url":"https://api.github.com/repos/apple/swift-package-manager/merges","archive_url":"https://api.github.com/repos/apple/swift-package-manager/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/apple/swift-package-manager/downloads","issues_url":"https://api.github.com/repos/apple/swift-package-manager/issues{/number}","pulls_url":"https://api.github.com/repos/apple/swift-package-manager/pulls{/number}","milestones_url":"https://api.github.com/repos/apple/swift-package-manager/milestones{/number}","notifications_url":"https://api.github.com/repos/apple/swift-package-manager/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/apple/swift-package-manager/labels{/name}","releases_url":"https://api.github.com/repos/apple/swift-package-manager/releases{/id}","deployments_url":"https://api.github.com/repos/apple/swift-package-manager/deployments","created_at":"2015-10-23T21:41:12Z","updated_at":"2016-02-28T15:01:54Z","pushed_at":"2016-02-28T13:04:05Z","git_url":"git://github.com/apple/swift-package-manager.git","ssh_url":"git@github.com:apple/swift-package-manager.git","clone_url":"https://github.com/apple/swift-package-manager.git","svn_url":"https://github.com/apple/swift-package-manager","homepage":"","size":859,"stargazers_count":3569,"watchers_count":3569,"language":"Swift","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":273,"mirror_url":null,"open_issues_count":9,"forks":273,"open_issues":9,"watchers":3569,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/apple/swift-package-manager/pulls/156"},"html":{"href":"https://github.com/apple/swift-package-manager/pull/156"},"issue":{"href":"https://api.github.com/repos/apple/swift-package-manager/issues/156"},"comments":{"href":"https://api.github.com/repos/apple/swift-package-manager/issues/156/comments"},"review_comments":{"href":"https://api.github.com/repos/apple/swift-package-manager/pulls/156/comments"},"review_comment":{"href":"https://api.github.com/repos/apple/swift-package-manager/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/apple/swift-package-manager/pulls/156/commits"},"statuses":{"href":"https://api.github.com/repos/apple/swift-package-manager/statuses/500911d87acd37cce4b4846d8c5b76c40068ba6c"}}}}