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

[WIP] Introduce Formatter #161

Closed
wants to merge 6 commits into from
Closed
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
193 changes: 184 additions & 9 deletions Sources/XcbeautifyLib/CaptureGroups.swift

Large diffs are not rendered by default.

52 changes: 10 additions & 42 deletions Sources/XcbeautifyLib/Parser.swift
Original file line number Diff line number Diff line change
@@ -1,17 +1,11 @@
public class Parser {

private let colored: Bool

private let renderer: OutputRendering

private let additionalLines: () -> String?

private(set) var summary: TestSummary? = nil
public private(set) var summary: TestSummary? = nil

private(set) var needToRecordSummary = false

public var preserveUnbeautifiedLines = false

public var outputType: OutputType = OutputType.undefined

private lazy var innerParsers: [InnerParser] = [
Expand Down Expand Up @@ -100,40 +94,27 @@ public class Parser {
// MARK: - Init

public init(
colored: Bool = true,
renderer: Renderer,
preserveUnbeautifiedLines: Bool = false,
additionalLines: @escaping () -> (String?)
) {
self.colored = colored

switch renderer {
case .terminal:
self.renderer = TerminalRenderer(colored: colored)
case .gitHubActions:
self.renderer = GitHubActionsRenderer()
}

self.preserveUnbeautifiedLines = preserveUnbeautifiedLines
self.additionalLines = additionalLines
}

public func parse(line: String) -> String? {
public func parse(line: String) -> CaptureGroup? {

// Find first parser that can parse specified string
guard let idx = innerParsers.firstIndex(where: { $0.regex.match(string: line)}) else {

// Some uncommon cases, which have additional logic and don't follow default flow

if Regex.executedWithoutSkipped.match(string: line) {
outputType = OutputType.task
parseSummary(line: line, colored: colored, skipped: false)
parseSummary(line: line, skipped: false)
return nil
}

if Regex.executedWithSkipped.match(string: line) {
outputType = OutputType.task
parseSummary(line: line, colored: colored, skipped: true)
parseSummary(line: line, skipped: true)
return nil
}

Expand All @@ -149,7 +130,7 @@ public class Parser {

// Nothing found?
outputType = OutputType.undefined
return preserveUnbeautifiedLines ? line : nil
return nil
}

let parser = innerParsers[idx]
Expand All @@ -160,17 +141,12 @@ public class Parser {
// Move found parser to the top, so next time it will be checked first
innerParsers.insert(innerParsers.remove(at: idx), at: 0)

return result.value
}

public func formattedSummary() -> String? {
guard let summary = summary else { return nil }
return renderer.format(testSummary: summary)
return result.captureGroup
}

// MARK: Private

private func parseSummary(line: String, colored: Bool, skipped: Bool) {
private func parseSummary(line: String, skipped: Bool) {
guard needToRecordSummary else { return }
defer { needToRecordSummary = false }

Expand All @@ -188,8 +164,6 @@ public class Parser {

private func innerParser(_ regex: Regex, outputType: OutputType) -> InnerParser {
return InnerParser(
additionalLines: additionalLines,
renderer: renderer,
regex: regex,
outputType: outputType
)
Expand All @@ -199,22 +173,16 @@ public class Parser {

fileprivate struct Result {
let outputType: OutputType
let value: String?
let captureGroup: CaptureGroup
}

let additionalLines: () -> String?
let renderer: OutputRendering
let regex: Regex
let outputType: OutputType

func parse(line: String) -> Result {
return Result(
outputType: outputType,
value: renderer.beautify(
line: line,
pattern: regex.pattern,
additionalLines: additionalLines
)
captureGroup: line.captureGroup(with: regex.pattern)
)
}
}
Expand Down
186 changes: 0 additions & 186 deletions Sources/XcbeautifyLib/Renderers/OutputRendering.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import Foundation
protocol OutputRendering {
var colored: Bool { get }

func beautify(line: String, pattern: Pattern, additionalLines: @escaping () -> (String?)) -> String?

func format(testSummary: TestSummary) -> String

func format(line: String, command: String, pattern: Pattern, arguments: String) -> String?
Expand Down Expand Up @@ -75,190 +73,6 @@ protocol OutputRendering {
func formatWriteFile(group: WriteFileCaptureGroup) -> String?
}

extension OutputRendering {
func beautify(
line: String,
pattern: Pattern,
additionalLines: @escaping () -> (String?)
) -> String? {
let group: CaptureGroup = line.captureGroup(with: pattern)

switch (pattern, group) {
case (.aggregateTarget, let group as AggregateTargetCaptureGroup):
return formatTargetCommand(command: "Aggregate", group: group)
case (.analyze, let group as AnalyzeCaptureGroup):
return formatAnalyze(group: group)
case (.analyzeTarget, let group as AnalyzeTargetCaptureGroup):
return formatTargetCommand(command: "Analyze", group: group)
case (.buildTarget, let group as BuildTargetCaptureGroup):
return formatTargetCommand(command: "Build", group: group)
case (.checkDependencies, _ as CheckDependenciesCaptureGroup):
return format(line: line, command: "Check Dependencies", pattern: .checkDependencies, arguments: "")
case (.checkDependenciesErrors, let group as CheckDependenciesErrorsCaptureGroup):
return formatError(group: group)
case (.clangError, let group as ClangErrorCaptureGroup):
return formatError(group: group)
case (.cleanRemove, let group as CleanRemoveCaptureGroup):
return formatCleanRemove(group: group)
case (.cleanTarget, let group as CleanTargetCaptureGroup):
return formatTargetCommand(command: "Clean", group: group)
case (.codesign, let group as CodesignCaptureGroup):
return formatCodeSign(group: group)
case (.codesignFramework, let group as CodesignFrameworkCaptureGroup):
return formatCodeSignFramework(group: group)
case (.compile, let group as CompileCaptureGroup):
return formatCompile(group: group)
case (.compileCommand, let group as CompileCommandCaptureGroup):
return formatCompileCommand(group: group)
case (.compileError, let group as CompileErrorCaptureGroup):
return formatCompileError(group: group, additionalLines: additionalLines)
case (.compileStoryboard, let group as CompileStoryboardCaptureGroup):
return formatCompile(group: group)
case (.compileWarning, let group as CompileWarningCaptureGroup):
return formatCompileWarning(group: group, additionalLines: additionalLines)
case (.compileXib, let group as CompileXibCaptureGroup):
return formatCompile(group: group)
case (.copyHeader, let group as CopyHeaderCaptureGroup):
return formatCopy(group: group)
case (.copyPlist, let group as CopyPlistCaptureGroup):
return formatCopy(group: group)
case (.copyStrings, let group as CopyStringsCaptureGroup):
return formatCopy(group: group)
case (.cpresource, let group as CpresourceCaptureGroup):
return formatCopy(group: group)
case (.cursor, let group as CursorCaptureGroup):
return formatCursor(group: group)
case (.duplicateLocalizedStringKey, let group as DuplicateLocalizedStringKeyCaptureGroup):
return formatDuplicateLocalizedStringKey(group: group)
case (.executedWithoutSkipped, let group as ExecutedWithoutSkippedCaptureGroup):
return formatExecutedWithoutSkipped(group: group)
case (.executedWithSkipped, let group as ExecutedWithSkippedCaptureGroup):
return formatExecutedWithSkipped(group: group)
case (.failingTest, let group as FailingTestCaptureGroup):
return formatFailingTest(group: group)
case (.fatalError, let group as FatalErrorCaptureGroup):
return formatError(group: group)
case (.fileMissingError, let group as FileMissingErrorCaptureGroup):
return formatFileMissingError(group: group)
case (.generateCoverageData, let group as GenerateCoverageDataCaptureGroup):
return formatGenerateCoverageData(group: group)
case (.generatedCoverageReport, let group as GeneratedCoverageReportCaptureGroup):
return formatCoverageReport(group: group)
case (.generateDsym, let group as GenerateDSYMCaptureGroup):
return formatGenerateDsym(group: group)
case (.genericWarning, let group as GenericWarningCaptureGroup):
return formatWarning(group: group)
case (.ldError, let group as LDErrorCaptureGroup):
return formatError(group: group)
case (.ldWarning, let group as LDWarningCaptureGroup):
return formatLdWarning(group: group)
case (.libtool, let group as LibtoolCaptureGroup):
return formatLibtool(group: group)
case (.linkerDuplicateSymbols, let group as LinkerDuplicateSymbolsCaptureGroup):
return formatLinkerDuplicateSymbolsError(group: group)
case (.linkerDuplicateSymbolsLocation, let group as LinkerDuplicateSymbolsLocationCaptureGroup):
return formatLinkerDuplicateSymbolsLocation(group: group)
case (.linkerUndefinedSymbolLocation, let group as LinkerUndefinedSymbolLocationCaptureGroup):
return formatLinkerUndefinedSymbolLocation(group: group)
case (.linkerUndefinedSymbols, let group as LinkerUndefinedSymbolsCaptureGroup):
return formatLinkerUndefinedSymbolsError(group: group)
case (.linking, let group as LinkingCaptureGroup):
return formatLinking(group: group)
case (.moduleIncludesError, let group as ModuleIncludesErrorCaptureGroup):
return formatError(group: group)
case (.noCertificate, let group as NoCertificateCaptureGroup):
return formatError(group: group)
case (.packageCheckingOut, let group as PackageCheckingOutCaptureGroup):
return formatPackageCheckingOut(group: group)
case (.packageFetching, let group as PackageFetchingCaptureGroup):
return formatPackageFetching(group: group)
case (.packageGraphResolvedItem, let group as PackageGraphResolvedItemCaptureGroup):
return formatPackageItem(group: group)
case (.packageGraphResolvingEnded, _ as PackageGraphResolvingEndedCaptureGroup):
return formatPackageEnd()
case (.packageGraphResolvingStart, _ as PackageGraphResolvingStartCaptureGroup):
return formatPackageStart()
case (.packageUpdating, let group as PackageUpdatingCaptureGroup):
return formatPackageUpdating(group: group)
case (.parallelTestCaseAppKitPassed, let group as ParallelTestCaseAppKitPassedCaptureGroup):
return formatParallelTestCaseAppKitPassed(group: group)
case (.parallelTestCaseFailed, let group as ParallelTestCaseFailedCaptureGroup):
return formatParallelTestCaseFailed(group: group)
case (.parallelTestCasePassed, let group as ParallelTestCasePassedCaptureGroup):
return formatParallelTestCasePassed(group: group)
case (.parallelTestingFailed, let group as ParallelTestingFailedCaptureGroup):
return formatParallelTestingFailed(line: line, group: group)
case (.parallelTestingPassed, let group as ParallelTestingPassedCaptureGroup):
return formatParallelTestingPassed(line: line, group: group)
case (.parallelTestingStarted, let group as ParallelTestingStartedCaptureGroup):
return formatParallelTestingStarted(line: line, group: group)
case (.parallelTestSuiteStarted, let group as ParallelTestSuiteStartedCaptureGroup):
return formatParallelTestSuiteStarted(group: group)
case (.pbxcp, let group as PbxcpCaptureGroup):
return formatCopy(group: group)
case (.phaseScriptExecution, let group as PhaseScriptExecutionCaptureGroup):
return formatPhaseScriptExecution(group: group)
case (.phaseSuccess, let group as PhaseSuccessCaptureGroup):
return formatPhaseSuccess(group: group)
case (.podsError, let group as PodsErrorCaptureGroup):
return formatError(group: group)
case (.preprocess, _ as PreprocessCaptureGroup):
return format(line: line, command: "Preprocessing", pattern: pattern, arguments: "$1")
case (.processInfoPlist, let group as ProcessInfoPlistCaptureGroup):
return formatProcessInfoPlist(group: group)
case (.processPch, let group as ProcessPchCaptureGroup):
return formatProcessPch(group: group)
case (.processPchCommand, let group as ProcessPchCommandCaptureGroup):
return formatProcessPchCommand(group: group)
case (.provisioningProfileRequired, let group as ProvisioningProfileRequiredCaptureGroup):
return formatError(group: group)
case (.restartingTest, let group as RestartingTestCaptureGroup):
return formatRestartingTest(line: line, group: group)
case (.shellCommand, let group as ShellCommandCaptureGroup):
return formatShellCommand(group: group)
case (.symbolReferencedFrom, _ as SymbolReferencedFromCaptureGroup):
return formatCompleteError(line: line)
case (.testCaseMeasured, let group as TestCaseMeasuredCaptureGroup):
return formatTestCaseMeasured(group: group)
case (.testCasePassed, let group as TestCasePassedCaptureGroup):
return formatTestCasePassed(group: group)
case (.testCasePending, let group as TestCasePendingCaptureGroup):
return formatTestCasePending(group: group)
case (.testCaseStarted, let group as TestCaseStartedCaptureGroup):
return formatTestCasesStarted(group: group)
case (.testsRunCompletion, let group as TestsRunCompletionCaptureGroup):
return formatTestsRunCompletion(group: group)
case (.testSuiteAllTestsFailed, let group as TestSuiteAllTestsFailedCaptureGroup):
return formatTestSuiteAllTestsFailed(group: group)
case (.testSuiteAllTestsPassed, let group as TestSuiteAllTestsPassedCaptureGroup):
return formatTestSuiteAllTestsPassed(group: group)
case (.testSuiteStart, let group as TestSuiteStartCaptureGroup):
return formatTestSuiteStart(group: group)
case (.testSuiteStarted, let group as TestSuiteStartedCaptureGroup):
return formatTestSuiteStarted(group: group)
case (.tiffutil, let group as TIFFutilCaptureGroup):
return formatTIFFUtil(group: group)
case (.touch, let group as TouchCaptureGroup):
return formatTouch(group: group)
case (.uiFailingTest, let group as UIFailingTestCaptureGroup):
return formatUIFailingTest(group: group)
case (.undefinedSymbolLocation, _ as UndefinedSymbolLocationCaptureGroup):
return formatCompleteWarning(line: line)
case (.willNotBeCodeSigned, let group as WillNotBeCodeSignedCaptureGroup):
return formatWillNotBeCodesignWarning(group: group)
case (.writeAuxiliaryFiles, let group as WriteAuxiliaryFilesCaptureGroup):
return formatWriteAuxiliaryFiles(group: group)
case (.writeFile, let group as WriteFileCaptureGroup):
return formatWriteFile(group: group)
case (.xcodebuildError, let group as XcodebuildErrorCaptureGroup):
return formatError(group: group)
case (_, _):
assertionFailure()
return nil
}
}
}

extension OutputRendering {

func format(line: String, command: String, pattern: Pattern, arguments: String) -> String? {
Expand Down
2 changes: 1 addition & 1 deletion Sources/XcbeautifyLib/TestSummary.swift
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
struct TestSummary {
public struct TestSummary {
let testsCount: Int
let skippedCount: Int
let failuresCount: Int
Expand Down
Loading