Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug fixed in recursive injection cases. #29

Merged
merged 2 commits into from
Oct 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions Binary/Sources/Deli/Extension/String+Range.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,27 @@
// Deli
//

extension String {
subscript (i: Int) -> Character {
return self[index(startIndex, offsetBy: i)]
}
subscript (i: Int) -> String {
return String(self[i])
}
subscript (r: CountableRange<Int>) -> String {
return String(self[r.lowerBound...(r.upperBound - 1)])
}
subscript (r: CountableClosedRange<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
let end = index(startIndex, offsetBy: r.upperBound)
return String(self[start...end])
}
subscript (r: CountablePartialRangeFrom<Int>) -> String {
let start = index(startIndex, offsetBy: r.lowerBound)
return String(self[start...])
}
}

extension String.UTF8View {
subscript (i: Int) -> Character? {
return self[i]?.first
Expand Down
62 changes: 31 additions & 31 deletions Binary/Sources/Deli/Runner/Parser/InjectParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ final class InjectParser: Parsable {

static let typeRefererSuffix = ".self"
static let injectFuncRegex = "Inject\\(([^\\(]*(\\([^\\)]*\\))*[^\\)]*)\\)".r!
static let argumentRegex = ",[\\s]*([^:]+:[\\s]*\\([^\\)]*\\))|[\\s]*([^,]+)".r!


static let qualifierName = "qualifier"
static let qualifierPrefix = "\(qualifierName):"
static let qualifierRegex = "\(qualifierName):[\\s]*\"([^\"]*)\"".r!
Expand All @@ -37,45 +36,47 @@ final class InjectParser: Parsable {
guard name == Constant.functionName || name.hasSuffix(".\(Constant.functionName)") else { return nil }
guard source.kind == Constant.functionCallKey else { return nil }

let callExpr: String = fileContent
.utf8[Int(source.offset)..<Int(source.offset + source.length)]?
.replacingOccurrences(of: Constant.typeRefererSuffix, with: "")
.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""

guard let callExprMatch = Constant.injectFuncRegex.findFirst(in: callExpr)?.group(at: 1) else {
Logger.log(.assert("Mismatched usage of `\(Constant.functionName)` method on SourceKitten result. \(callExpr)"))
Logger.log(.error("Unknown error.", source.getSourceLine(with: fileContent)))
throw ParserError.unknown
}

let arguments = try Constant.argumentRegex
.findAll(in: callExprMatch.trimmingCharacters(in: .whitespacesAndNewlines))
.map { match -> String in
guard let result = match.group(at: 1) ?? match.group(at: 2) else {
Logger.log(.error("Failed to parse argument `\(match.source)`.", source.getSourceLine(with: fileContent)))
throw ParserError.parseErrorArguments
let arguments: [String] = {
let list = source.substructures
.map { source in
return fileContent.utf8[Int(source.offset)..<Int(source.offset + source.length)] ?? ""
}
return result
}
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }
.filter { !$0.isEmpty }
.map { $0.trimmingCharacters(in: .whitespacesAndNewlines) }

guard list.isEmpty else { return list }

/// Bug fixed in the empty substructure of SourceKittenFramework.
guard let sourceData = fileContent.utf8[Int(source.offset)..<Int(source.offset + source.length)] else { return [] }
guard !sourceData.contains(",") else { return [] }
guard let type = Constant.injectFuncRegex.findFirst(in: sourceData)?.group(at: 1) else { return [] }
return [type]
}()


guard let firstArgument = arguments.first else {
Logger.log(.error("The `\(Constant.functionName)` method in `\(name)` required arguments.", source.getSourceLine(with: fileContent)))
throw ParserError.emptyArguments
}

let typeName: String = {
if firstArgument.hasSuffix(Constant.typeRefererSuffix) {
return firstArgument[0..<(firstArgument.count - Constant.typeRefererSuffix.count)]
} else {
return firstArgument
}
}()

let qualifier = arguments
.first { $0.contains(Constant.qualifierPrefix) }
.first { $0.hasPrefix(Constant.qualifierPrefix) }
.flatMap { result -> String? in
guard let match = Constant.qualifierRegex.findFirst(in: result) else { return nil }
return match.group(at: 1)
}?
.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""

let isPayload = arguments.contains { $0.contains(Constant.payloadPrefix) }
let isPayload = arguments.contains { $0.hasPrefix(Constant.payloadPrefix) }

if let arrayMatch = Constant.arrayRegex.findFirst(in: firstArgument), let arrayType = arrayMatch.group(at: 1) {
if let arrayMatch = Constant.arrayRegex.findFirst(in: typeName), let arrayType = arrayMatch.group(at: 1) {
return Dependency(
parent: rootName,
target: source,
Expand All @@ -87,7 +88,7 @@ final class InjectParser: Parsable {
return Dependency(
parent: rootName,
target: source,
name: arguments[0],
name: typeName,
rule: isPayload ? .payload : .default,
qualifier: qualifier
)
Expand All @@ -98,11 +99,10 @@ final class InjectParser: Parsable {

var queue = source.substructures
while let item = queue.popLast() {
guard let dependency = try found(item, root: source, fileContent: fileContent) else {
queue.append(contentsOf: item.substructures)
continue
queue.append(contentsOf: item.substructures)
if let dependency = try found(item, root: source, fileContent: fileContent) {
dependencyList.append(dependency)
}
dependencyList.append(dependency)
}

return dependencyList
Expand Down
46 changes: 23 additions & 23 deletions Tests/DeliTests/DeliSample/DeliFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ final class DeliFactory: ModuleFactory {
register(
AccountService.self,
resolver: {
let _AccountConfiguration = context.get(AccountConfiguration.self, qualifier: "")!
return _AccountConfiguration.accountService() as AnyObject
let parent = context.get(AccountConfiguration.self, qualifier: "")!
return parent.accountService() as AnyObject
},
qualifier: "facebook",
scope: .singleton
Expand All @@ -38,33 +38,33 @@ final class DeliFactory: ModuleFactory {
return FactoryTest(payload: payload as! TestPayload)
},
injector: { instance in
let _AccountService = context.get(AccountService.self, qualifier: "")!
instance.inject(facebook: _AccountService)
let _0 = context.get(AccountService.self, qualifier: "facebook")!
instance.inject(facebook: _0)
},
qualifier: ""
).link(FactoryTest.self)
registerFactory(
FriendInfoViewModel.self,
resolver: { payload in
let _AccountService = context.get(AccountService.self, qualifier: "")!
return FriendInfoViewModel(_AccountService, payload: payload as! FriendPayload)
let _0 = context.get(AccountService.self, qualifier: "")!
return FriendInfoViewModel(_0, payload: payload as! FriendPayload)
},
qualifier: ""
).link(FriendInfoViewModel.self)
register(
FriendListViewModel.self,
resolver: {
let _FriendService = context.get(FriendService.self, qualifier: "")!
return FriendListViewModel(_FriendService)
let _0 = context.get(FriendService.self, qualifier: "")!
return FriendListViewModel(_0)
},
qualifier: "",
scope: .singleton
)
register(
FriendServiceImpl.self,
resolver: {
let _AccountService = context.get(AccountService.self, qualifier: "")!
return FriendServiceImpl(_AccountService)
let _0 = context.get(AccountService.self, qualifier: "")!
return FriendServiceImpl(_0)
},
qualifier: "",
scope: .singleton
Expand All @@ -80,19 +80,19 @@ final class DeliFactory: ModuleFactory {
register(
LibraryService.self,
resolver: {
let _TestService = context.get(TestService.self, qualifier: "")!
let _Book = context.get([Book].self, qualifier: "")
return LibraryService(qualifierTest: _TestService, _Book)
let _0 = context.get(TestService.self, qualifier: "qualifierTest")!
let _1 = context.get([Book].self, qualifier: "")
return LibraryService(qualifierTest: _0, _1)
},
qualifier: "",
scope: .singleton
)
register(
MessageServiceImpl.self,
resolver: {
let _FriendService = context.get(FriendService.self, qualifier: "")!
let _AccountService = context.get(AccountService.self, qualifier: "")!
return MessageServiceImpl(_FriendService, _AccountService)
let _0 = context.get(FriendService.self, qualifier: "")!
let _1 = context.get(AccountService.self, qualifier: "")!
return MessageServiceImpl(_0, _1)
},
qualifier: "",
scope: .singleton
Expand All @@ -111,18 +111,18 @@ final class DeliFactory: ModuleFactory {
return TestService()
},
injector: { instance in
let _FriendServiceImpl = context.get(FriendServiceImpl.self, qualifier: "")!
instance.inject(_FriendServiceImpl)
let _0 = context.get(FriendServiceImpl.self, qualifier: "")!
instance.inject(_0)
},
qualifier: "qualifierTest",
scope: .singleton
)
register(
TestViewModel.self,
resolver: {
let _AccountService = context.get(AccountService.self, qualifier: "")!
let _FriendService = context.get(FriendService.self, qualifier: "")!
return TestViewModel(_AccountService, _FriendService)
let _0 = context.get(AccountService.self, qualifier: "")!
let _1 = context.get(FriendService.self, qualifier: "")!
return TestViewModel(_0, _1)
},
qualifier: "",
scope: .prototype
Expand All @@ -138,8 +138,8 @@ final class DeliFactory: ModuleFactory {
registerFactory(
UserViewModel.self,
resolver: { payload in
let _AccountService = context.get(AccountService.self, qualifier: "")!
return UserViewModel(_AccountService, payload: payload as! UserPayload)
let _0 = context.get(AccountService.self, qualifier: "")!
return UserViewModel(_0, payload: payload as! UserPayload)
},
qualifier: ""
).link(UserViewModel.self)
Expand Down