Commit 39c72258 authored by Drew's avatar Drew

Technical preview

parents
.atllbuild
bin
*.sublime-workspace
/*Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.*/
import Darwin
protocol CarolineEngine {
func testAll(tests: [CarolineTest])
}
public class CarolineCoreEngine : CarolineEngine {
public func testAll(tests: [CarolineTest]) {
setvbuf(stdout, nil, _IOLBF, 0)
for test in tests {
if test.skip {
var state = CarolineState(test: test)
state.outcome = .Skipped
state.commit()
continue
}
print("test \(test) started.")
test.test()
print("test \(test) ended.")
}
//count failures
var failures = 0
var skipped = 0
for test in tests {
let state = CarolineState(test: test)
if state.outcome == .Failed { failures += 1}
if state.outcome == .Skipped { skipped += 1}
}
print("Test execution finished with \(tests.count) tests and \(failures) failures.")
print ("Skipped \(skipped) tests.")
}
public init() { }
}
\ No newline at end of file
/*Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.*/
///All tests should conform to this protocol
public protocol CarolineTest: class {
///Implement the test behavior here
func test()
var skip: Bool { get }
}
public extension CarolineTest {
var skip: Bool { return false }
}
/*Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.*/
///We use this to associate various bits of storage with a test
///Without requiring the test to allocate its own storage for our use
private var carolineStates: [ObjectIdentifier:CarolineState] = [:]
internal struct CarolineState {
///The test associated with this state
let test: CarolineTest
///The test's current state
var outcome : Outcome
///Read the current state for the test.
///Call .commit() to update it.
init(test: CarolineTest) {
//todo: thread safety
if let state = carolineStates[ObjectIdentifier(test)] {
self = state
return
}
self.outcome = .Initial
self.test = test
carolineStates[ObjectIdentifier(test)] = self
}
///Commits the update to the global state.
func commit() {
//todo: thread safety
carolineStates[ObjectIdentifier(test)] = self
}
}
\ No newline at end of file
/*Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.*/
//MARK: Functions
extension CarolineTest {
public final func assert(@autoclosure condition: () -> Bool, @autoclosure _ message: () -> String = "Test failed", file: String = #file, line: Int = #line) {
if !condition() {
var state = CarolineState(test: self)
state.outcome = .Failed
state.commit()
print("Test failed at \(file):\(line) - \(message())")
}
}
}
\ No newline at end of file
/*Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.*/
enum Outcome {
///No other state was assigned for this test
case Initial
///The test passed
case Passed
///The test failed
case Failed
///The test was skipped
case Skipped
}
\ No newline at end of file
# Caroline
Caroline is a new, pure-Swift testing framework.
# Why Caroline
* Because updating `allTests` by hand is unmanageable
* Because subtle platform differences in XCTest make writing portable tests too hard.
* To boldly design new Swift APIs instead of being stuck in the ObjC past.
* To fix many design errors and architectural annoyances. I am *constantly* running into things "not contemplated" by XCTest design.
* To introduce groundbreaking new features that have never been seen in a test framework before.
* To avoid a dependence on Foundation. You read that right.
# Editions
Caroline comes in two editions. *I'm preparing you now.*
* CarolineCore is a free, MIT-licensed edition. I plan to support all the popular features of XCTest, but better and saner.
* CarolinePro is a commercial edition. It includes advanced features designed to make working programmers far more productive with their tests than they are today. Full source code is available for study and customization.
Caroline is borne out of many lifetimes of frustration at other testing frameworks. I hope you will not have to suffer as I did.
(package
:name "Caroline"
:tasks {
:statictool {
:tool "atllbuild"
:output-type "executable"
:name "caroline_static_tool"
:sources ["caroline-static-tool/**.swift"]
:publish-product true
}
:debug {
:dependencies ["statictool"]
:tool "shell"
:script ".atllbuild/products/caroline_static_tool --core caroline-static-tool-tests/fixtures/SampleTests/foo.swift"
}
:core {
:tool "atllbuild"
:output-type "static-library"
:name "CarolineCore"
:sources ["CarolineCore/**.swift"]
}
:simpletest-gen {
:tool "shell"
:script "bin/caroline_static_tool --core tests/SimpleTest/foo.swift > tests/SimpleTest/main.swift"
:dependencies ["statictool"]
}
:simpletest-build {
:dependencies ["core" "simpletest-gen"]
:tool "atllbuild"
:output-type "executable"
:name "SimpleTest"
:sources ["tests/SimpleTest/**.swift"]
:link-with ["CarolineCore.a"]
:publish-product true
}
:simpletest {
:dependencies ["simpletest-build"]
:tool "shell"
:script "bin/SimpleTest"
}
}
)
\ No newline at end of file
print("hello world")
class A:CarolineTest{
}
class B :CarolineTest{
}
class C: CarolineTest{
}
class D:CarolineTest{
}
class E:CarolineTest{}
class F : CarolineTest{}
class G :CarolineTest {}
class H: CarolineTest {}
class I : CarolineTest {}
class Z: NSObject {
class J: CarolineTest { }
class K : CarolineTest { }
}
\ No newline at end of file
/*Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.*/
import Darwin
enum FileUtilsError: ErrorProtocol {
case OpenError(Int)
case ReadError(Int)
case CloseError(Int)
case UTF8Error
}
extension String {
init(fromFile fileName: String) throws {
let file = open(fileName, O_RDONLY)
var completeFile: [CChar] = []
//CANNOT defer cleaning up this resource
//PAY ATTENTION
if file == -1 { throw FileUtilsError.OpenError(Int(errno)) }
readLoop: while true {
var buf = [CChar](repeating: 0, count: 4096)
let bytesRead = buf.withUnsafeMutableBufferPointer {
return read(file, $0.baseAddress, $0.count)
}
switch(bytesRead) {
case 0:
break readLoop //EOF
case -1:
close(file) //CLEAN UP open resource
throw FileUtilsError.ReadError(Int(errno))
default:
completeFile.append(contentsOf: buf[0..<bytesRead])
}
}
// holy shit, UB if we don't append a zero here
// https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20160404/001633.html
completeFile.append(0)
guard let str = String(validatingUTF8: completeFile) else {
close(file)
throw FileUtilsError.UTF8Error
}
self.init(str)
if close(file) != 0 {
throw FileUtilsError.CloseError(Int(errno))
}
}
}
\ No newline at end of file
/*Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.*/
/// StandBack is a regular expression engine implementing the `egrep` (POSIX-extended) language. It is cross-platform and has no dependencies.
/// While egrep is a less popular language than PCRE, it is fully capable for basic programming tasks, and our API is *much* easier to use than Foundation's.
/// let r = try! Regex(pattern: "class[[:space:]]+([[:alnum:]]+)[[:space:]]*:CarolineTest[[:space:]]*\\{")
/// print(try! r.match("prefix stuff class Foo:CarolineTest {"))
import Darwin
enum RegexError: ErrorProtocol {
/////The regexec() function failed to match
case NoMatch
///Invalid regular expression
case BadPattern
///invalid collating element
case Collation
///invalid character class
case CharacterClass
///`\' applied to unescapable character
case Escape
/// Invalid backreference number
case SubExpression
/// brackets `[ ]' not balanced
case BracketBalance
/// parentheses `( )' not balanced
case ParenthesesBalance
/// braces `{ }' not balanced
case BraceBalance
/// invalid character range in `[ ]'
case Range
/// ran out of memory
case OutOfMemory
/// `?', `*', or `+' operand invalid
case Repeat
/// empty (sub)expression
case Empty
/// cannot happen - you found a bug [in libc]
case Bug
/// e.g. negative-length string
case InvalidArgument
/// (bad multibyte character)
case IllegalByteSequence
/// An error not in the POSIX specification.
case ErrorNotInSpecification(Int)
init(fromRegDiagnostic diagnostic: Int32) {
switch(diagnostic) {
case REG_NOMATCH:
self = RegexError.NoMatch
case REG_BADPAT:
self = RegexError.BadPattern
case REG_ECOLLATE:
self = RegexError.Collation
case REG_ECTYPE:
self = RegexError.CharacterClass
case REG_EESCAPE:
self = RegexError.Escape
case REG_ESUBREG:
self = RegexError.SubExpression
case REG_EBRACK:
self = RegexError.BracketBalance
case REG_EPAREN:
self = RegexError.ParenthesesBalance
case REG_EBRACE:
self = RegexError.BraceBalance
case REG_ERANGE:
self = RegexError.Range
case REG_ESPACE:
self = RegexError.OutOfMemory
case REG_BADRPT:
self = RegexError.Repeat
case REG_EMPTY:
self = RegexError.Empty
case REG_ASSERT:
self = RegexError.Bug
case REG_INVARG:
self = RegexError.InvalidArgument
case REG_ILLSEQ:
self = RegexError.IllegalByteSequence
default:
self = RegexError.ErrorNotInSpecification(Int(diagnostic))
}
}
}
///We use an inner class as an implementation detail. It isn't actually mutable, but it's hard to convince Swift that.
private final class RegexImp {
private let regext: regex_t
init(pattern: String) throws {
var lregext = regex_t()
let result = regcomp(&lregext, pattern, REG_EXTENDED)
if result != 0 {
throw RegexError(fromRegDiagnostic: result)
}
self.regext = lregext
}
deinit {
var regext = self.regext
regfree(&regext)
}
}
///A match object.
struct Match : CustomStringConvertible, CustomDebugStringConvertible {
/// The start of the match
let start : Int
/// The end of the match
let end : Int
///The string we searched to generate this match
let underlyingString : String
///The part of the string that matched this expression
var region: String {
let utf8 = self.underlyingString.utf8
return String(utf8[utf8.startIndex.advanced(by: start)..<utf8.startIndex.advanced(by: end)])
}
private init?(start: Int, end: Int, underlyingString: String) {
if start == -1 && end == -1 {return nil}
self.start = start
self.end = end
self.underlyingString = underlyingString
}
private init?(regmatch: regmatch_t, underlyingString: String) {
self.init(start: Int(regmatch.rm_so), end: Int(regmatch.rm_eo), underlyingString: underlyingString)
}
var description: String {
return region
}
var debugDescription: String {
return "<Match: \(region)>"
}
}
class Foo:AnyObject {
}
struct FindResult {
///The entire part of the string that matched.
let entireMatch: Match
///Each group of the match. Specify a group in parentheses.
///The `k`th group is the `k`th parentheses expression in the regex.
///If the group was unused, the element will be nil
let groups: [Match?]
}
class FindResultGenerator: IteratorProtocol {
typealias Element = FindResult
var lastStart: Int = -1
var lastMatch: Match? = nil
let string: String
let regex: Regex
internal func next() -> FindResultGenerator.Element? {
let startPosition = lastStart + (lastMatch?.end ?? 0) + 1
lastStart = startPosition
let proposedStartIndex = string.utf8.startIndex.advanced(by: startPosition, limit: string.utf8.endIndex)
let abbreviatedString = String(string.utf8[proposedStartIndex..<string.utf8.endIndex])!
let result = try! regex.findFirst(inString: abbreviatedString)
lastMatch = result?.entireMatch
return result
}
init(regex: Regex, string: String) { self.regex = regex; self.string = string }
}
class FindResultSequence: Sequence {
let generator: FindResultGenerator
init(regex: Regex, string: String) { self.generator = FindResultGenerator(regex: regex, string: string) }
typealias Generator = FindResultGenerator
func makeIterator() -> FindResultGenerator {
return generator
}
}
struct Regex {
private let regexImp : RegexImp
init(pattern: String) throws {
regexImp = try RegexImp(pattern: pattern)
}
///Finds the first match in the given string.
func findFirst(inString string: String) throws -> FindResult? {
self.regexImp.regext.re_nsub
var weDontMutateThis = self.regexImp.regext
var matches: [regmatch_t] = [regmatch_t](repeating: regmatch_t(), count: self.regexImp.regext.re_nsub + 1)
let result = regexec(&weDontMutateThis, string, matches.count, &matches, 0)
if result == REG_NOMATCH { return nil }
if result != 0 {
throw RegexError(fromRegDiagnostic: result)
}
var swiftMatches: [Match?] = []
for m in matches [1..<matches.count]{
let swiftMatch = Match(regmatch: m, underlyingString: string)
swiftMatches.append(swiftMatch)
}
return FindResult(entireMatch: Match(regmatch: matches[0], underlyingString: string)!, groups: swiftMatches)
}
/// Find all matches in the sequence.
/// - attention: Iterating over the return value **consumes** results.
/// - complexity: Results are found lazily. Calling this function does not actually find anything: we perform the find later when you loop over the result. This is because if you stop iterating after the first N matches you don't pay the cost to find them all.
/// ...*However*. iterating over results *consumes* them, which may be unexpected.
/// If you need to iterate over these results several times, pass the return value to an `Array` constructor. Then we will find all the results right away and place them into the array where you can work with them at your leisure.
func findAll(inString string: String) -> FindResultSequence {
return FindResultSequence(regex: self, string: string)
}
}
/*
Copyright (C) 2016 Drew Crawford
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the names of the copyright holders nor the names of any
contributors may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
import Darwin
func usage() {
print("caroline-static-tool 0.1-dev")
print("Usage: caroline-static-tool --core file1.swift file2.swift file3.swift > /path/to/main.swift")
}
if Process.arguments.count < 3 {
usage()
exit(1)
}
precondition(Process.arguments[1] == "--core", "Non-core is unsupported")
let fileNames = Process.arguments[2..<Process.arguments.count]
var s = ""
s += "/*\n"
s += "Copyright (C) 2016 Drew Crawford\n"
s += "All rights reserved.\n"
s += "\n"
s += "Redistribution and use in source and binary forms, with or without\n"
s += "modification, are permitted provided that the following conditions\n"
s += "are met:\n"
s += "1. Redistributions of source code must retain the above copyright\n"
s += " notice, this list of conditions and the following disclaimer.\n"
s += "2. Redistributions in binary form must reproduce the above copyright\n"
s += " notice, this list of conditions and the following disclaimer in the\n"
s += " documentation and/or other materials provided with the distribution.\n"
s += "3. Neither the names of the copyright holders nor the names of any\n"
s += " contributors may be used to endorse or promote products derived from this\n"
s += " software without specific prior written permission.\n"
s += "\n"
s += "THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n"
s += "AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n"
s += "IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n"
s += "ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE\n"
s += "LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n"
s += "CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n"
s += "SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n"
s += "INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n"
s += "CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n"
s += "ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\n"
s += "POSSIBILITY OF SUCH DAMAGE.\n"
s += "*/\n"
print(s)
print()
print("// This file is automatically generated by Caroline and should not be edited by hand.")
print ("import CarolineCore")
print("let allTests: [CarolineTest] = [")
var i = 0
for file in fileNames {