Skip to content
Open
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
11 changes: 3 additions & 8 deletions Resources/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,14 +195,9 @@ function loadMainData() {
targets = buildData.filter(function (step) {
return step.type === 'target' && step.fetchedFromCache === false;
});
cFiles = buildData.filter(function (step) {
return step.type === 'detail' && step.detailStepType === cCompilation
&& step.fetchedFromCache === false;
});
swiftFiles = buildData.filter(function (step) {
return step.type === 'detail' && step.detailStepType === swiftCompilation
&& step.fetchedFromCache === false;
});
// buildData only has the main step and the targets here, the counts come from top_files.js
cFiles = new Array(cFilesCount);
swiftFiles = new Array(swiftFilesCount);
}

function loadTargetData(target) {
Expand Down
11 changes: 3 additions & 8 deletions Sources/XCLogParser/generated/HtmlReporterResources.swift
Original file line number Diff line number Diff line change
Expand Up @@ -287,14 +287,9 @@ function loadMainData() {
targets = buildData.filter(function (step) {
return step.type === 'target' && step.fetchedFromCache === false;
});
cFiles = buildData.filter(function (step) {
return step.type === 'detail' && step.detailStepType === cCompilation
&& step.fetchedFromCache === false;
});
swiftFiles = buildData.filter(function (step) {
return step.type === 'detail' && step.detailStepType === swiftCompilation
&& step.fetchedFromCache === false;
});
// buildData only has the main step and the targets here, the counts come from top_files.js
cFiles = new Array(cFilesCount);
swiftFiles = new Array(swiftFilesCount);
}

function loadTargetData(target) {
Expand Down
19 changes: 6 additions & 13 deletions Sources/XCLogParser/parser/IDEActivityLogSection+Parsing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -44,27 +44,18 @@ extension IDEActivityLogSection {
// for the `(in target 'ABC' from project Project)` string
let isFlatten = subSections.contains { $0.getTargetFromCommand() != nil }
if isFlatten {
let mainTarget = "$MainTarget"
let targetsDictionary = subSections.reduce(
[String: IDEActivityLogSection]()) { targets, subSection -> [String: IDEActivityLogSection] in
// some substeps belong to the root project, we use a fixed name for them
let targetName = subSection.getTargetFromCommand() ?? mainTarget
// sections without a target (build description, module scans) are grouped as one
let targetName = subSection.getTargetFromCommand() ?? Self.buildSystemTarget
let target = getOrBuildTarget(targetName, in: targets, using: subSection)
target.subSections.append(subSection)
var updatedTargets = targets
updatedTargets[targetName] = target
return updatedTargets
}
let nonMainTargets = targetsDictionary.filter { (key: String, _) -> Bool in
return key != mainTarget
}
var subSections = [IDEActivityLogSection]()
if let mainTarget = targetsDictionary[mainTarget] {
subSections.append(contentsOf: mainTarget.subSections)
}
subSections.append(contentsOf: nonMainTargets.values)
let withTargets = self
withTargets.subSections = subSections.sorted { lhs, rhs -> Bool in
withTargets.subSections = targetsDictionary.values.sorted { lhs, rhs -> Bool in
lhs.timeStartedRecording < rhs.timeStartedRecording
}
return withTargets
Expand Down Expand Up @@ -136,10 +127,12 @@ extension IDEActivityLogSection {
return buildTargetSection(name, with: section)
}

static let buildSystemTarget = "Build system"

private func buildTargetSection(_ name: String, with section: IDEActivityLogSection) -> IDEActivityLogSection {
return IDEActivityLogSection(sectionType: 2,
domainType: section.domainType,
title: "Build target \(name)",
title: name == Self.buildSystemTarget ? name : "Build target \(name)",
signature: name,
timeStartedRecording: section.timeStartedRecording,
timeStoppedRecording: section.timeStoppedRecording,
Expand Down
23 changes: 13 additions & 10 deletions Sources/XCLogParser/reporter/HtmlReporter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -243,26 +243,25 @@ public struct HtmlReporter: LogReporter {
swiftTypeCheckTimes.sort { $0.durationMS > $1.durationMS }
let topTypeChecks = Array(swiftTypeCheckTimes.prefix(Self.maxSwifTypeChecks))

try write(
slowestSwiftFiles: Array(swiftSteps.prefix(Self.maxSlowestFiles)),
slowestCFiles: Array(cSteps.prefix(Self.maxSlowestFiles)),
swiftFunctionTimes: topFunctions,
swiftTypeCheckTimes: topTypeChecks,
toDir: buildDir)
try write(swiftSteps: swiftSteps,
cSteps: cSteps,
swiftFunctionTimes: topFunctions,
swiftTypeCheckTimes: topTypeChecks,
toDir: buildDir)

}

private func write(slowestSwiftFiles: [BuildStep],
slowestCFiles: [BuildStep],
private func write(swiftSteps: [BuildStep],
cSteps: [BuildStep],
swiftFunctionTimes: [SwiftFunctionTime],
swiftTypeCheckTimes: [SwiftTypeCheck],
toDir buildDir: String) throws {
let encoder = JSONEncoder()
encoder.outputFormatting = .prettyPrinted
let functionsJson = try encoder.encode(swiftFunctionTimes)
let typeChecksJson = try encoder.encode(swiftTypeCheckTimes)
let swiftJson = try encoder.encode(slowestSwiftFiles)
let cJson = try encoder.encode(slowestCFiles)
let swiftJson = try encoder.encode(Array(swiftSteps.prefix(Self.maxSlowestFiles)))
let cJson = try encoder.encode(Array(cSteps.prefix(Self.maxSlowestFiles)))
guard let functionsString = String(data: functionsJson, encoding: .utf8),
let typeChecksString = String(data: typeChecksJson, encoding: .utf8),
let swiftString = String(data: swiftJson, encoding: .utf8),
Expand All @@ -278,6 +277,10 @@ public struct HtmlReporter: LogReporter {
const topSwiftFunctions = \(functionsString);

const topSwifTypeChecks = \(typeChecksString);

const swiftFilesCount = \(swiftSteps.count);

const cFilesCount = \(cSteps.count);
""".write(toFile: "\(buildDir)/js/top_files.js", atomically: true, encoding: .utf8)
}
}
61 changes: 61 additions & 0 deletions Tests/XCLogParserTests/GroupedByTargetTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import XCTest
@testable import XCLogParser

class GroupedByTargetTests: XCTestCase {

func testUntaggedSectionsAreGroupedUnderOneTarget() {
let main = makeSection(title: "Build", subSections: [
makeSection(title: "Create build description", start: 0),
makeSection(title: "Compiling Clang module Foundation", start: 1),
makeSection(title: "CompileC a.o", command: "CompileC a.o (in target 'Foo' from project 'P')", start: 2),
makeSection(title: "Compiling Clang module UIKit", start: 3),
makeSection(title: "CompileC b.o", command: "CompileC b.o (in target 'Bar' from project 'P')", start: 4),
])

let grouped = main.groupedByTarget()

XCTAssertEqual(["Build system", "Build target Foo", "Build target Bar"],
grouped.subSections.map { $0.title })
let buildSystem = grouped.subSections[0]
XCTAssertEqual(["Create build description",
"Compiling Clang module Foundation",
"Compiling Clang module UIKit"],
buildSystem.subSections.map { $0.title })
}

func testTargetsKeepTheirOrder() {
let main = makeSection(title: "Build", subSections: [
makeSection(title: "Ld Bar", command: "Ld Bar (in target 'Bar' from project 'P')", start: 2),
makeSection(title: "CompileC a.o", command: "CompileC a.o (in target 'Foo' from project 'P')", start: 1),
])

XCTAssertEqual(["Build target Foo", "Build target Bar"],
main.groupedByTarget().subSections.map { $0.title })
}

private func makeSection(title: String,
command: String = "",
start: Double = 0,
subSections: [IDEActivityLogSection] = []) -> IDEActivityLogSection {
return IDEActivityLogSection(sectionType: 1,
domainType: "",
title: title,
signature: "",
timeStartedRecording: start,
timeStoppedRecording: start,
subSections: subSections,
text: "",
messages: [],
wasCancelled: false,
isQuiet: false,
wasFetchedFromCache: false,
subtitle: "",
location: DVTDocumentLocation(documentURLString: "", timestamp: 0.0),
commandDetailDesc: command,
uniqueIdentifier: "",
localizedResultString: "",
xcbuildSignature: "",
attachments: [],
unknown: 0)
}
}
30 changes: 30 additions & 0 deletions Tests/XCLogParserTests/HtmlReporterTests.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import XCTest
@testable import XCLogParser

class HtmlReporterTests: XCTestCase {

func testIndexFileCountsComeFromAllTargets() throws {
let compile = { (title: String, type: DetailStepType) -> BuildStep in
makeFakeBuildStep(title: title, type: .detail, detailStepType: type,
startTimestamp: 0, fetchedFromCache: false)
}
let foo = makeFakeBuildStep(title: "Build target Foo", type: .target, detailStepType: .none,
startTimestamp: 0, fetchedFromCache: false)
.with(subSteps: [compile("Compile a.swift", .swiftCompilation),
compile("Compile b.swift", .swiftCompilation),
compile("Compile c.c", .cCompilation)])
let bar = makeFakeBuildStep(title: "Build target Bar", type: .target, detailStepType: .none,
startTimestamp: 0, fetchedFromCache: false)
.with(subSteps: [compile("Compile d.swift", .swiftCompilation)])
let build = makeFakeBuildStep(title: "Build", type: .main, detailStepType: .none,
startTimestamp: 0, fetchedFromCache: false)
.with(subSteps: [foo, bar])
let dir = try TestUtils.createRandomTestDir()

try HtmlReporter().report(build: build, output: FileOutput(path: dir.path), rootOutput: dir.path)

let topFiles = try String(contentsOf: dir.appendingPathComponent("js/top_files.js"))
XCTAssertTrue(topFiles.contains("const swiftFilesCount = 3;"))
XCTAssertTrue(topFiles.contains("const cFilesCount = 1;"))
}
}
21 changes: 21 additions & 0 deletions Tests/XCLogParserTests/XCTestManifests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,25 @@ extension ChromeTracerOutputTests {
]
}

extension GroupedByTargetTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__GroupedByTargetTests = [
("testTargetsKeepTheirOrder", testTargetsKeepTheirOrder),
("testUntaggedSectionsAreGroupedUnderOneTarget", testUntaggedSectionsAreGroupedUnderOneTarget),
]
}

extension HtmlReporterTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
// to regenerate.
static let __allTests__HtmlReporterTests = [
("testIndexFileCountsComeFromAllTargets", testIndexFileCountsComeFromAllTargets),
]
}

extension IssuesReporterTests {
// DO NOT MODIFY: This is autogenerated, use:
// `swift test --generate-linuxmain`
Expand Down Expand Up @@ -146,6 +165,8 @@ public func __allTests() -> [XCTestCaseEntry] {
return [
testCase(ActivityParserTests.__allTests__ActivityParserTests),
testCase(ChromeTracerOutputTests.__allTests__ChromeTracerOutputTests),
testCase(GroupedByTargetTests.__allTests__GroupedByTargetTests),
testCase(HtmlReporterTests.__allTests__HtmlReporterTests),
testCase(IssuesReporterTests.__allTests__IssuesReporterTests),
testCase(LexRedactorTests.__allTests__LexRedactorTests),
testCase(LexerTests.__allTests__LexerTests),
Expand Down