Skip to content

Commit

Permalink
feat: improve error message of ModuleMapMapper (#3733)
Browse files Browse the repository at this point in the history
* feat: improve error message of ModuleMapMapper

* docs: changelog

* feat: improve error message of ModuleMapMapper
  • Loading branch information
danieleformichelli authored Nov 26, 2021
1 parent 1048202 commit 69d6a87
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ Please, check out guidelines: https://keepachangelog.com/en/1.0.0/

## Next

### Fixed

- Improve error message in case `ModuleMapMapper` fails to retrieve a dependency [#3733](https://github.com/tuist/tuist/pull/3733) by [@danyf90](https://github.com/danyf90)

## 2.3.1 - Avantgarde

### Fixed
Expand Down
66 changes: 57 additions & 9 deletions Sources/TuistGenerator/Mappers/ModuleMapMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,37 @@ import Foundation
import TSCBasic
import TuistCore
import TuistGraph
import TuistSupport

enum ModuleMapMapperError: FatalError {
case invalidTargetDependency(sourceProject: AbsolutePath, sourceTarget: String, dependentTarget: String)
case invalidProjectTargetDependency(sourceProject: AbsolutePath, sourceTarget: String, dependentProject: AbsolutePath, dependentTarget: String)

/// Error type.
var type: ErrorType {
switch self {
case .invalidTargetDependency, .invalidProjectTargetDependency: return .abort
}
}

/// Error description.
var description: String {
switch self {
case let .invalidTargetDependency(sourceProject, sourceTarget, dependentTarget):
return """
Target '\(sourceTarget)' of the project at path '\(sourceProject.pathString)' \
depends on a target '\(dependentTarget)' that can't be found. \
Please make sure your project configuration is correct.
"""
case let .invalidProjectTargetDependency(sourceProject, sourceTarget, dependentProject, dependentTarget):
return """
Target '\(sourceTarget)' of the project at path '\(sourceProject.pathString)' \
depends on a target '\(dependentTarget)' of the project at path '\(dependentProject.pathString)' that can't be found. \
Please make sure your project configuration is correct.
"""
}
}
}

/// Mapper that maps the `MODULE_MAP` build setting to the `-fmodule-map-file` compiler flags.
/// It is required to avoid embedding the module map into the frameworks during cache operations, which would make the framework not portable, as
Expand All @@ -21,9 +52,9 @@ public final class ModuleMapMapper: WorkspaceMapping {
public func map(workspace: WorkspaceWithProjects) throws -> (WorkspaceWithProjects, [SideEffectDescriptor]) {
let (projectsByPath, targetsByName) = Self.makeProjectsByPathWithTargetsByName(workspace: workspace)
var targetToModuleMaps: [TargetID: Set<AbsolutePath>] = [:]
workspace.projects.forEach { project in
project.targets.forEach { target in
Self.dependenciesModuleMaps(
try workspace.projects.forEach { project in
try project.targets.forEach { target in
try Self.dependenciesModuleMaps(
workspace: workspace,
project: project,
target: target,
Expand Down Expand Up @@ -87,14 +118,14 @@ public final class ModuleMapMapper: WorkspaceMapping {
/// Calculates the set of module maps to be linked to a given target and populates the `targetToModuleMaps` dictionary.
/// Each target must link the module map of its direct and indirect dependencies.
/// The `targetToModuleMaps` is also used as cache to avoid recomputing the set for already computed targets.
private static func dependenciesModuleMaps(
private static func dependenciesModuleMaps( // swiftlint:disable:this function_body_length
workspace: WorkspaceWithProjects,
project: Project,
target: Target,
targetToModuleMaps: inout [TargetID: Set<AbsolutePath>],
projectsByPath: [AbsolutePath: Project],
targetsByName: [String: Target]
) {
) throws {
let targetID = TargetID(projectPath: project.path, targetName: target.name)
if targetToModuleMaps[targetID] != nil {
// already computed
Expand All @@ -107,16 +138,33 @@ public final class ModuleMapMapper: WorkspaceMapping {
let dependentTarget: Target
switch dependency {
case let .target(name):
guard let dependentTargetFromName = targetsByName[name] else {
throw ModuleMapMapperError.invalidTargetDependency(
sourceProject: project.path,
sourceTarget: target.name,
dependentTarget: name
)
}
dependentProject = project
dependentTarget = targetsByName[name]!
dependentTarget = dependentTargetFromName
case let .project(name, path):
dependentProject = projectsByPath[path]!
dependentTarget = targetsByName[name]!
guard let dependentProjectFromPath = projectsByPath[path],
let dependentTargetFromName = targetsByName[name]
else {
throw ModuleMapMapperError.invalidProjectTargetDependency(
sourceProject: project.path,
sourceTarget: target.name,
dependentProject: path,
dependentTarget: name
)
}
dependentProject = dependentProjectFromPath
dependentTarget = dependentTargetFromName
case .framework, .xcframework, .library, .package, .sdk, .xctest:
continue
}

Self.dependenciesModuleMaps(
try Self.dependenciesModuleMaps(
workspace: workspace,
project: dependentProject,
target: dependentTarget,
Expand Down

0 comments on commit 69d6a87

Please sign in to comment.