Skip to content
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
8 changes: 4 additions & 4 deletions Sources/SWBCore/CapturedBuildInfo.swift
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,16 @@ public struct CapturedBuildInfo: PropertyListItemConvertible, Sendable {
let settings = settingsPerTarget[configuredTarget]
let targetConstructionComponents = settings?.constructionComponents
let projectXcconfigSettings: CapturedBuildSettingsTableInfo = {
let settings = targetConstructionComponents?.projectXcconfigSettings?.capturedRepresentation ?? [:]
return CapturedBuildSettingsTableInfo(name: CapturedBuildSettingsTableInfo.Name.projectXcconfig, path: targetConstructionComponents?.projectXcconfigPath, settings: settings)
let settings = targetConstructionComponents?.projectXcconfig?.settings.capturedRepresentation ?? [:]
return CapturedBuildSettingsTableInfo(name: CapturedBuildSettingsTableInfo.Name.projectXcconfig, path: targetConstructionComponents?.projectXcconfig?.path, settings: settings)
}()
let projectSettings: CapturedBuildSettingsTableInfo = {
let settings = targetConstructionComponents?.projectSettings?.capturedRepresentation ?? [:]
return CapturedBuildSettingsTableInfo(name: CapturedBuildSettingsTableInfo.Name.project, path: nil, settings: settings)
}()
let targetXcconfigSettings: CapturedBuildSettingsTableInfo = {
let settings = targetConstructionComponents?.targetXcconfigSettings?.capturedRepresentation ?? [:]
return CapturedBuildSettingsTableInfo(name: CapturedBuildSettingsTableInfo.Name.targetXcconfig, path: targetConstructionComponents?.targetXcconfigPath, settings: settings)
let settings = targetConstructionComponents?.targetXcconfig?.settings.capturedRepresentation ?? [:]
return CapturedBuildSettingsTableInfo(name: CapturedBuildSettingsTableInfo.Name.targetXcconfig, path: targetConstructionComponents?.targetXcconfig?.path, settings: settings)
}()
let targetSettings: CapturedBuildSettingsTableInfo = {
let settings = targetConstructionComponents?.targetSettings?.capturedRepresentation ?? [:]
Expand Down
16 changes: 8 additions & 8 deletions Sources/SWBCore/Dependencies.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,11 +196,11 @@ public struct ModuleDependenciesContext: Sendable, SerializableCodable {
{
self.init(sourceRange: .init(path: location.path, startLine: location.endLine, startColumn: location.endColumn, endLine: location.endLine, endColumn: location.endColumn), modificationStyle: .appendToExistingAssignment)
}
else if let path = settings.constructionComponents.targetXcconfigPath {
self.init(sourceRange: .init(path: path, startLine: .max, startColumn: .max, endLine: .max, endColumn: .max), modificationStyle: .insertNewAssignment(targetNameCondition: nil))
else if let xcconfig = settings.constructionComponents.targetXcconfig {
self.init(sourceRange: .init(path: xcconfig.path, startLine: xcconfig.finalLineNumber, startColumn: xcconfig.finalColumnNumber, endLine: xcconfig.finalLineNumber, endColumn: xcconfig.finalColumnNumber), modificationStyle: .insertNewAssignment(targetNameCondition: nil))
}
else if let path = settings.constructionComponents.projectXcconfigPath {
self.init(sourceRange: .init(path: path, startLine: .max, startColumn: .max, endLine: .max, endColumn: .max), modificationStyle: .insertNewAssignment(targetNameCondition: target.name))
else if let xcconfig = settings.constructionComponents.projectXcconfig {
self.init(sourceRange: .init(path: xcconfig.path, startLine: xcconfig.finalLineNumber, startColumn: xcconfig.finalColumnNumber, endLine: xcconfig.finalLineNumber, endColumn: xcconfig.finalColumnNumber), modificationStyle: .insertNewAssignment(targetNameCondition: target.name))
}
else {
return nil
Expand Down Expand Up @@ -357,11 +357,11 @@ public struct HeaderDependenciesContext: Sendable, SerializableCodable {
{
self.init(sourceRange: .init(path: location.path, startLine: location.endLine, startColumn: location.endColumn, endLine: location.endLine, endColumn: location.endColumn), modificationStyle: .appendToExistingAssignment)
}
else if let path = settings.constructionComponents.targetXcconfigPath {
self.init(sourceRange: .init(path: path, startLine: .max, startColumn: .max, endLine: .max, endColumn: .max), modificationStyle: .insertNewAssignment(targetNameCondition: nil))
else if let xcconfig = settings.constructionComponents.targetXcconfig {
self.init(sourceRange: .init(path: xcconfig.path, startLine: xcconfig.finalLineNumber, startColumn: xcconfig.finalColumnNumber, endLine: xcconfig.finalLineNumber, endColumn: xcconfig.finalColumnNumber), modificationStyle: .insertNewAssignment(targetNameCondition: nil))
}
else if let path = settings.constructionComponents.projectXcconfigPath {
self.init(sourceRange: .init(path: path, startLine: .max, startColumn: .max, endLine: .max, endColumn: .max), modificationStyle: .insertNewAssignment(targetNameCondition: target.name))
else if let xcconfig = settings.constructionComponents.projectXcconfig {
self.init(sourceRange: .init(path: xcconfig.path, startLine: xcconfig.finalLineNumber, startColumn: xcconfig.finalColumnNumber, endLine: xcconfig.finalLineNumber, endColumn: xcconfig.finalColumnNumber), modificationStyle: .insertNewAssignment(targetNameCondition: target.name))
}
else {
return nil
Expand Down
10 changes: 8 additions & 2 deletions Sources/SWBCore/MacroConfigFileLoader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@ import Foundation

/// Whether we failed to read the file at all. If this is `true`, the macro table is guaranteed to be empty.
@_spi(Testing) public let isFileReadFailure: Bool

/// The final line number after parsing completes.
let finalLineNumber: Int

/// The final column number after parsing completes.
let finalColumnNumber: Int
}

@_spi(Testing) public enum MacroConfigLoadContext: Sendable {
Expand All @@ -54,7 +60,7 @@ final class MacroConfigFileLoader: Sendable {
guard let data = try? fs.read(path) else {
let table = MacroValueAssignmentTable(namespace: namespace)
let dependencyPaths = [path]
return MacroConfigInfo(table: table, diagnostics: [], dependencyPaths: dependencyPaths, signature: filesSignature(dependencyPaths), isFileReadFailure: true)
return MacroConfigInfo(table: table, diagnostics: [], dependencyPaths: dependencyPaths, signature: filesSignature(dependencyPaths), isFileReadFailure: true, finalLineNumber: 1, finalColumnNumber: 1)
}

return loadSettingsFromConfig(data: data, path: path, namespace: namespace, searchPaths: searchPaths, filesSignature: filesSignature)
Expand Down Expand Up @@ -287,7 +293,7 @@ final class MacroConfigFileLoader: Sendable {
let delegate = SettingsConfigFileParserDelegate(fs: fs, basePath: path?.dirname, searchPaths: searchPaths, table: tableRef, diagnostics: diagnostics, nestedConfigurations: nestedConfigs, ancestorIncludes: ancestorIncludes, developerPath: core.developerPath)
let parser = MacroConfigFileParser(byteString: data, path: path ?? Path("no path to xcconfig file provided"), delegate: delegate)
parser.parse()
return MacroConfigInfo(table: tableRef.table, diagnostics: diagnostics.diagnostics, dependencyPaths: nestedConfigs.paths, signature: filesSignature(nestedConfigs.paths), isFileReadFailure: false)
return MacroConfigInfo(table: tableRef.table, diagnostics: diagnostics.diagnostics, dependencyPaths: nestedConfigs.paths, signature: filesSignature(nestedConfigs.paths), isFileReadFailure: false, finalLineNumber: parser.finalLineNumber, finalColumnNumber: parser.finalColumnNumber)
}
}

Expand Down
45 changes: 18 additions & 27 deletions Sources/SWBCore/Settings/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -786,19 +786,16 @@ public final class Settings: PlatformBuildContext, Sendable {
///
/// - remark: The overhead of this object should be very small, because the majority of the actual data are the linked lists of macro definitions, which are shared with the main table in the `Settings` object.
public struct ConstructionComponents: Sendable {
// These properties are the individual tables (and info about them) of specific levels which contributed to the Settings.
struct XcconfigInfo: Sendable {
var path: Path
var settings: MacroValueAssignmentTable
var finalLineNumber: Int
var finalColumnNumber: Int
}

/// The path to the project-level xcconfig file.
let projectXcconfigPath: Path?
/// The project-level xcconfig settings table.
let projectXcconfigSettings: MacroValueAssignmentTable?
/// The project-level settings table.
let projectXcconfig: XcconfigInfo?
let projectSettings: MacroValueAssignmentTable?
/// The path to the target-level xcconfig file.
let targetXcconfigPath: Path?
/// The target-level xcconfig settings table.
let targetXcconfigSettings: MacroValueAssignmentTable?
/// The target-level settings table.
let targetXcconfig: XcconfigInfo?
let targetSettings: MacroValueAssignmentTable?

// These properties are the actual tables of settings up to a certain point, which are used to compute the resolved values of settings at that level in the build settings editor (e.g., in the Levels view).
Expand Down Expand Up @@ -966,9 +963,9 @@ public final class Settings: PlatformBuildContext, Sendable {
return BuildSettingsEditorInfoPayload(
// Assigned values
targetSettingAssignments: assignedValues(for: constructionComponents.targetSettings),
targetXcconfigSettingAssignments: assignedValues(for: constructionComponents.targetXcconfigSettings),
targetXcconfigSettingAssignments: assignedValues(for: constructionComponents.targetXcconfig?.settings),
projectSettingAssignments: assignedValues(for: constructionComponents.projectSettings),
projectXcconfigSettingAssignments: assignedValues(for: constructionComponents.projectXcconfigSettings),
projectXcconfigSettingAssignments: assignedValues(for: constructionComponents.projectXcconfig?.settings),

// Resolved values
targetResolvedSettingsValues: resolvedValues(for: constructionComponents.upToTargetSettings),
Expand Down Expand Up @@ -1322,18 +1319,16 @@ private class SettingsBuilder {
return core.coreSettings
}

private var projectXcconfigPath: Path? = nil
private var projectXcconfigSettings: MacroValueAssignmentTable? = nil
private var projectXcconfig: Settings.ConstructionComponents.XcconfigInfo? = nil
private var projectSettings: MacroValueAssignmentTable? = nil
private var targetXcconfigPath: Path? = nil
private var targetXcconfigSettings: MacroValueAssignmentTable? = nil
private var targetXcconfig: Settings.ConstructionComponents.XcconfigInfo? = nil
private var targetSettings: MacroValueAssignmentTable? = nil
/// Convenient array for iterating over all defined settings tables in the project for this target, from lowest to highest.
private var allProjectSettingsLevels: [(table: MacroValueAssignmentTable?, path: Path?, level: String)] {
return [
(projectXcconfigSettings, projectXcconfigPath, "project-xcconfig"),
(projectXcconfig?.settings, projectXcconfig?.path, "project-xcconfig"),
(projectSettings, nil, "project"),
(targetXcconfigSettings, targetXcconfigPath, "target-xcconfig"),
(targetXcconfig?.settings, targetXcconfig?.path, "target-xcconfig"),
(targetSettings, nil, "target"),
]
}
Expand All @@ -1347,11 +1342,9 @@ private class SettingsBuilder {
/// The project model components which were used to construct the settings made by this builder.
var constructionComponents: Settings.ConstructionComponents {
return Settings.ConstructionComponents(
projectXcconfigPath: self.projectXcconfigPath,
projectXcconfigSettings: self.projectXcconfigSettings,
projectXcconfig: self.projectXcconfig,
projectSettings: self.projectSettings,
targetXcconfigPath: self.targetXcconfigPath,
targetXcconfigSettings: self.targetXcconfigSettings,
targetXcconfig: self.targetXcconfig,
targetSettings: self.targetSettings,
upToDefaultsSettings: self.upToDefaultsSettings,
upToProjectXcconfigSettings: upToProjectXcconfigSettings,
Expand Down Expand Up @@ -2807,8 +2800,7 @@ private class SettingsBuilder {
}

// Save the settings table as part of the construction components.
self.projectXcconfigPath = path
self.projectXcconfigSettings = info.table
self.projectXcconfig = .init(path: path, settings: info.table, finalLineNumber: info.finalLineNumber, finalColumnNumber: info.finalColumnNumber)

// Also save the table we've constructed so far.
self.upToProjectXcconfigSettings = MacroValueAssignmentTable(copying: _table)
Expand Down Expand Up @@ -3015,8 +3007,7 @@ private class SettingsBuilder {
}

// Save the settings table as part of the construction components.
self.targetXcconfigPath = path
self.targetXcconfigSettings = info.table
self.targetXcconfig = .init(path: path, settings: info.table, finalLineNumber: info.finalLineNumber, finalColumnNumber: info.finalColumnNumber)

// Save the table we've constructed so far.
self.upToTargetXcconfigSettings = MacroValueAssignmentTable(copying: _table)
Expand Down
17 changes: 17 additions & 0 deletions Sources/SWBMacro/MacroConfigFileParser.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ public final class MacroConfigFileParser {
/// Current line number. Starts at one.
var currLine: Int

/// The final line number after parsing completes.
public private(set) var finalLineNumber: Int = 1

/// The final column number after parsing completes.
public private(set) var finalColumnNumber: Int = 1

/// Index of the start of the current line in the byte array.
private var currentLineStartIdx: Int = 0


/// Initializes the macro expression parser with the given string and delegate. How the string is parsed depends on the particular parse method that’s invoked, such as `parseAsString()` or `parseAsStringList()`, and not on the configuration of the parser.
public init(byteString: ByteString, path: Path, delegate: (any MacroConfigFileParserDelegate)?) {
Expand All @@ -55,6 +64,9 @@ public final class MacroConfigFileParser {
/// Returns the current line number of the parser. This is commonly used from the custom implementations of the parser delegate function callbacks. Line numbers are one-based, and refer only to the source text of the parser itself (not taking into account any source text included using #include directives).
public var lineNumber: Int { return currLine }

/// Returns the current column number of the parser. Column numbers are one-based.
public var columnNumber: Int { return currIdx - currentLineStartIdx + 1 }

/*

Grammar:
Expand Down Expand Up @@ -131,6 +143,7 @@ public final class MacroConfigFileParser {
}
advance(advancement)
currLine += 1
currentLineStartIdx = currIdx
}


Expand Down Expand Up @@ -461,6 +474,10 @@ public final class MacroConfigFileParser {

// At this point, we expect to have seen all of the input string.
assert(isAtEndOfStream)

// Set the final line and column numbers
finalLineNumber = currLine
finalColumnNumber = columnNumber
}


Expand Down
12 changes: 9 additions & 3 deletions Tests/SWBBuildSystemTests/DependencyValidationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
//
//===----------------------------------------------------------------------===//

import Foundation
import SWBCore
import SWBTestSupport
import SWBUtil
Expand Down Expand Up @@ -412,6 +413,11 @@ fileprivate struct DependencyValidationTests: CoreBasedTests {
"""
}

let projectXCConfigContents = try #require(tester.fs.read(projectXCConfigPath).stringValue)
let projectXCConfigLines = projectXCConfigContents.components(separatedBy: .newlines)
let projectXCConfigFinalLineNumber = projectXCConfigLines.count
let projectXCConfigFinalColumnNumber = (projectXCConfigLines.last?.count ?? 0) + 1

let expectedDiagsByTarget: [String: [Diagnostic]] = [
"TargetA": [
Diagnostic(
Expand All @@ -437,11 +443,11 @@ fileprivate struct DependencyValidationTests: CoreBasedTests {
"TargetB": [
Diagnostic(
behavior: .error,
location: Diagnostic.Location.path(projectXCConfigPath, line: .max, column: .max),
location: Diagnostic.Location.path(projectXCConfigPath, line: projectXCConfigFinalLineNumber, column: projectXCConfigFinalColumnNumber),
data: DiagnosticData("Missing entries in MODULE_DEPENDENCIES: Foundation"),
fixIts: [
Diagnostic.FixIt(
sourceRange: Diagnostic.SourceRange(path: projectXCConfigPath, startLine: .max, startColumn: .max, endLine: .max, endColumn: .max),
sourceRange: Diagnostic.SourceRange(path: projectXCConfigPath, startLine: projectXCConfigFinalLineNumber, startColumn: projectXCConfigFinalColumnNumber, endLine: projectXCConfigFinalLineNumber, endColumn: projectXCConfigFinalColumnNumber),
newText: "\nMODULE_DEPENDENCIES[target=TargetB] = $(inherited) \\\n Foundation\n"),
],
childDiagnostics: [
Expand All @@ -450,7 +456,7 @@ fileprivate struct DependencyValidationTests: CoreBasedTests {
location: Diagnostic.Location.path(swiftSourcePath, line: 1, column: 8),
data: DiagnosticData("Missing entry in MODULE_DEPENDENCIES: Foundation"),
fixIts: [Diagnostic.FixIt(
sourceRange: Diagnostic.SourceRange(path: projectXCConfigPath, startLine: .max, startColumn: .max, endLine: .max, endColumn: .max),
sourceRange: Diagnostic.SourceRange(path: projectXCConfigPath, startLine: projectXCConfigFinalLineNumber, startColumn: projectXCConfigFinalColumnNumber, endLine: projectXCConfigFinalLineNumber, endColumn: projectXCConfigFinalColumnNumber),
newText: "\nMODULE_DEPENDENCIES[target=TargetB] = $(inherited) \\\n Foundation\n")],
),
]),
Expand Down
Loading
Loading