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

Fix for resource synthesizers not added to the tuist edit project #4822

Merged
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
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -286,4 +286,4 @@ DEPENDENCIES
zeitwerk (~> 2.4)

BUNDLED WITH
2.2.33
2.2.33
14 changes: 13 additions & 1 deletion Sources/TuistKit/ProjectEditor/ProjectEditor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ final class ProjectEditor: ProjectEditing {
/// Utility to locate the custom templates directory
let templatesDirectoryLocator: TemplatesDirectoryLocating

/// Utility to locate the resource synthesizers directory
let resourceSynthesizersDirectoryLocator: ResourceSynthesizerPathLocating
devyhan marked this conversation as resolved.
Show resolved Hide resolved

private let cacheDirectoryProviderFactory: CacheDirectoriesProviderFactoring
private let projectDescriptionHelpersBuilderFactory: ProjectDescriptionHelpersBuilderFactoring

Expand All @@ -74,6 +77,7 @@ final class ProjectEditor: ProjectEditing {
helpersDirectoryLocator: HelpersDirectoryLocating = HelpersDirectoryLocator(),
writer: XcodeProjWriting = XcodeProjWriter(),
templatesDirectoryLocator: TemplatesDirectoryLocating = TemplatesDirectoryLocator(),
resourceSynthesizersDirectoryLocator: ResourceSynthesizerPathLocating = ResourceSynthesizerPathLocator(),
cacheDirectoryProviderFactory: CacheDirectoriesProviderFactoring = CacheDirectoriesProviderFactory(),
projectDescriptionHelpersBuilderFactory: ProjectDescriptionHelpersBuilderFactoring =
ProjectDescriptionHelpersBuilderFactory()
Expand All @@ -85,6 +89,7 @@ final class ProjectEditor: ProjectEditing {
self.helpersDirectoryLocator = helpersDirectoryLocator
self.writer = writer
self.templatesDirectoryLocator = templatesDirectoryLocator
self.resourceSynthesizersDirectoryLocator = resourceSynthesizersDirectoryLocator
self.cacheDirectoryProviderFactory = cacheDirectoryProviderFactory
self.projectDescriptionHelpersBuilderFactory = projectDescriptionHelpersBuilderFactory
}
Expand Down Expand Up @@ -135,6 +140,10 @@ final class ProjectEditor: ProjectEditing {
FileHandler.shared.glob($0, glob: "**/*.swift") + FileHandler.shared.glob($0, glob: "**/*.stencil")
} ?? []

let resourceSynthesizers = resourceSynthesizersDirectoryLocator.locate(at: editingPath).map {
FileHandler.shared.glob($0, glob: "**/*.stencil")
} ?? []

let editablePluginManifests = locateEditablePluginManifests(
at: editingPath,
excluding: pathsToExclude,
Expand All @@ -149,7 +158,9 @@ final class ProjectEditor: ProjectEditing {
)

/// We error if the user tries to edit a project in a directory where there are no editable files.
if projectManifests.isEmpty, editablePluginManifests.isEmpty, helpers.isEmpty, templates.isEmpty {
if projectManifests.isEmpty, editablePluginManifests.isEmpty, helpers.isEmpty, templates.isEmpty,
resourceSynthesizers.isEmpty
{
throw ProjectEditorError.noEditableFiles(editingPath)
}

Expand All @@ -169,6 +180,7 @@ final class ProjectEditor: ProjectEditing {
pluginProjectDescriptionHelpersModule: builtPluginHelperModules,
helpers: helpers,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath.parentDirectory
)

Expand Down
16 changes: 16 additions & 0 deletions Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ protocol ProjectEditorMapping: AnyObject {
pluginProjectDescriptionHelpersModule: [ProjectDescriptionHelpersModule],
helpers: [AbsolutePath],
templates: [AbsolutePath],
resourceSynthesizers: [AbsolutePath],
projectDescriptionSearchPath: AbsolutePath
) throws -> Graph
}
Expand All @@ -37,6 +38,7 @@ final class ProjectEditorMapper: ProjectEditorMapping {
pluginProjectDescriptionHelpersModule: [ProjectDescriptionHelpersModule],
helpers: [AbsolutePath],
templates: [AbsolutePath],
resourceSynthesizers: [AbsolutePath],
projectDescriptionSearchPath: AbsolutePath
) throws -> Graph {
let swiftVersion = try System.shared.swiftVersion()
Expand All @@ -59,6 +61,7 @@ final class ProjectEditorMapper: ProjectEditorMapping {
tuistPath: tuistPath,
helpers: helpers,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
configPath: configPath,
dependenciesPath: dependenciesPath,
editablePluginTargets: editablePluginManifests.map(\.name),
Expand Down Expand Up @@ -131,6 +134,7 @@ final class ProjectEditorMapper: ProjectEditorMapping {
tuistPath: AbsolutePath,
helpers: [AbsolutePath],
templates: [AbsolutePath],
resourceSynthesizers: [AbsolutePath],
configPath: AbsolutePath?,
dependenciesPath: AbsolutePath?,
editablePluginTargets: [String],
Expand Down Expand Up @@ -194,6 +198,17 @@ final class ProjectEditorMapper: ProjectEditorMapping {
)
}()

let resourceSynthesizersTarget: Target? = {
guard !resourceSynthesizers.isEmpty else { return nil }
return editorHelperTarget(
name: Constants.resourceSynthesizersDirectoryName,
filesGroup: manifestsFilesGroup,
targetSettings: baseTargetSettings,
sourcePaths: resourceSynthesizers,
dependencies: helpersTarget.flatMap { [TargetDependency.target(name: $0.name)] } ?? []
)
}()

let helperTargetDependencies = helpersTarget.map { [TargetDependency.target(name: $0.name)] } ?? []
let helperAndPluginDependencies = helperTargetDependencies + editablePluginTargetDependencies

Expand Down Expand Up @@ -221,6 +236,7 @@ final class ProjectEditorMapper: ProjectEditorMapping {
let targets = [
helpersTarget,
templatesTarget,
resourceSynthesizersTarget,
configTarget,
dependenciesTarget,
]
Expand Down
23 changes: 18 additions & 5 deletions Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import TuistCore
import TuistGraph
import TuistSupport

protocol ResourceSynthesizerPathLocating {
public protocol ResourceSynthesizerPathLocating {
func locate(at: AbsolutePath) -> AbsolutePath?

func templatePath(
for pluginName: String,
resourceName: String,
Expand Down Expand Up @@ -39,16 +41,16 @@ enum ResourceSynthesizerPathLocatorError: FatalError, Equatable {
}
}

final class ResourceSynthesizerPathLocator: ResourceSynthesizerPathLocating {
public final class ResourceSynthesizerPathLocator: ResourceSynthesizerPathLocating {
private let rootDirectoryLocator: RootDirectoryLocating

init(
public init(
rootDirectoryLocator: RootDirectoryLocating = RootDirectoryLocator()
) {
self.rootDirectoryLocator = rootDirectoryLocator
}

func templatePath(
public func templatePath(
for pluginName: String,
resourceName: String,
resourceSynthesizerPlugins: [PluginResourceSynthesizer]
Expand All @@ -67,7 +69,7 @@ final class ResourceSynthesizerPathLocator: ResourceSynthesizerPathLocating {
return resourceTemplatePath
}

func templatePath(
public func templatePath(
for resourceName: String,
path: AbsolutePath
) -> AbsolutePath? {
Expand All @@ -80,4 +82,15 @@ final class ResourceSynthesizerPathLocator: ResourceSynthesizerPathLocating {
)
return FileHandler.shared.exists(templatePath) ? templatePath : nil
}

// MARK: - Helpers

public func locate(at: AbsolutePath) -> AbsolutePath? {
guard let rootDirectory = rootDirectoryLocator.locate(from: at) else { return nil }
let helpersDirectory = rootDirectory
.appending(component: Constants.tuistDirectoryName)
.appending(component: Constants.resourceSynthesizersDirectoryName)
if !FileHandler.shared.exists(helpersDirectory) { return nil }
return helpersDirectory
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,9 @@ public final class MockResourceSynthesizerPathLocator: ResourceSynthesizerPathLo
) -> AbsolutePath? {
templatePathResourceStub?(resourceName, path)
}

public var locateStub: ((AbsolutePath) -> AbsolutePath?)?
public func locate(at: TSCBasic.AbsolutePath) -> TSCBasic.AbsolutePath? {
locateStub?(at)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ final class MockProjectEditorMapper: ProjectEditorMapping {
pluginProjectDescriptionHelpersModule: [ProjectDescriptionHelpersModule],
helpers: [AbsolutePath],
templates: [AbsolutePath],
resourceSynthesizers: [AbsolutePath],
projectDescriptionPath: AbsolutePath
)] = []

Expand All @@ -37,6 +38,7 @@ final class MockProjectEditorMapper: ProjectEditorMapping {
pluginProjectDescriptionHelpersModule: [ProjectDescriptionHelpersModule],
helpers: [AbsolutePath],
templates: [AbsolutePath],
resourceSynthesizers: [AbsolutePath],
projectDescriptionSearchPath: AbsolutePath
) throws -> Graph {
mapArgs.append((
Expand All @@ -51,6 +53,7 @@ final class MockProjectEditorMapper: ProjectEditorMapping {
pluginProjectDescriptionHelpersModule: pluginProjectDescriptionHelpersModule,
helpers: helpers,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionPath: projectDescriptionSearchPath
))

Expand Down
33 changes: 32 additions & 1 deletion Tests/TuistKitTests/ProjectEditor/ProjectEditorMapperTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
let dependenciesPath = sourceRootPath.appending(components: Constants.tuistDirectoryName, "Dependencies.swift")
let helperPaths = [sourceRootPath].map { $0.appending(component: "Project+Template.swift") }
let templates = [sourceRootPath].map { $0.appending(component: "template") }
let resourceSynthesizers = [sourceRootPath].map { $0.appending(component: "resourceSynthesizer") }
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
let projectName = "Manifests"
Expand All @@ -55,6 +56,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
pluginProjectDescriptionHelpersModule: [],
helpers: helperPaths,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath
)

Expand All @@ -67,7 +69,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
// Then
XCTAssertEqual(graph.name, "TestManifests")

XCTAssertEqual(targets.count, 7)
XCTAssertEqual(targets.count, 8)

// Generated Manifests target
let manifestsTarget = try XCTUnwrap(project.targets.first(where: { $0.name == sourceRootPath.basename + projectName }))
Expand Down Expand Up @@ -123,6 +125,23 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
.target(name: "ProjectDescriptionHelpers"),
]))

// Generated ResourceSynthesizers target
let resourceSynthesizersTarget = try XCTUnwrap(project.targets.last(where: { $0.name == "ResourceSynthesizers" }))
XCTAssertTrue(targets.contains(resourceSynthesizersTarget))

XCTAssertEqual(resourceSynthesizersTarget.name, "ResourceSynthesizers")
XCTAssertEqual(resourceSynthesizersTarget.platform, .macOS)
XCTAssertEqual(resourceSynthesizersTarget.product, .staticFramework)
XCTAssertEqual(
resourceSynthesizersTarget.settings,
expectedSettings(includePaths: [projectDescriptionPath, projectDescriptionPath.parentDirectory])
)
XCTAssertEqual(resourceSynthesizersTarget.sources.map(\.path), resourceSynthesizers)
XCTAssertEqual(resourceSynthesizersTarget.filesGroup, projectsGroup)
XCTAssertEqual(Set(resourceSynthesizersTarget.dependencies), Set([
.target(name: "ProjectDescriptionHelpers"),
]))

// Generated Config target
let configTarget = try XCTUnwrap(project.targets.last(where: { $0.name == "Config" }))
XCTAssertTrue(targets.contains(configTarget))
Expand Down Expand Up @@ -187,6 +206,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
let projectManifestPaths = [sourceRootPath].map { $0.appending(component: "Project.swift") }
let helperPaths: [AbsolutePath] = []
let templates: [AbsolutePath] = []
let resourceSynthesizers: [AbsolutePath] = []
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
let projectName = "Manifests"
Expand All @@ -205,6 +225,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
pluginProjectDescriptionHelpersModule: [],
helpers: helperPaths,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath
)

Expand Down Expand Up @@ -267,6 +288,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
]
let helperPaths: [AbsolutePath] = []
let templates: [AbsolutePath] = []
let resourceSynthesizers: [AbsolutePath] = []
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
let projectName = "Manifests"
Expand All @@ -284,6 +306,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
pluginProjectDescriptionHelpersModule: [],
helpers: helperPaths,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath
)

Expand Down Expand Up @@ -371,6 +394,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
}
let helperPaths: [AbsolutePath] = []
let templates: [AbsolutePath] = []
let resourceSynthesizers: [AbsolutePath] = []
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
let projectName = "Plugins"
Expand All @@ -389,6 +413,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
pluginProjectDescriptionHelpersModule: [],
helpers: helperPaths,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath
)

Expand Down Expand Up @@ -448,6 +473,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
}
let helperPaths: [AbsolutePath] = []
let templates: [AbsolutePath] = []
let resourceSynthesizers: [AbsolutePath] = []
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
let projectName = "Plugins"
Expand All @@ -466,6 +492,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
pluginProjectDescriptionHelpersModule: [],
helpers: helperPaths,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath
)

Expand Down Expand Up @@ -548,6 +575,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
]
let helperPaths: [AbsolutePath] = []
let templates: [AbsolutePath] = []
let resourceSynthesizers: [AbsolutePath] = []
let projectDescriptionPath = sourceRootPath.appending(component: "ProjectDescription.framework")
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
try createFiles([
Expand Down Expand Up @@ -577,6 +605,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
pluginProjectDescriptionHelpersModule: [],
helpers: helperPaths,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath
)

Expand All @@ -596,6 +625,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
let projectManifestPaths = [sourceRootPath].map { $0.appending(component: "Project.swift") }
let helperPaths: [AbsolutePath] = [sourceRootPath].map { $0.appending(components: "Tuist", "ProjectDescriptionHelpers") }
let templates: [AbsolutePath] = []
let resourceSynthesizers: [AbsolutePath] = []
let projectDescriptionPath = sourceRootPath.appending(components: "Frameworks", "ProjectDescription.framework")
let tuistPath = AbsolutePath("/usr/bin/foo/bar/tuist")
let manifestsProjectName = "Manifests"
Expand All @@ -618,6 +648,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase {
pluginProjectDescriptionHelpersModule: [remotePlugin],
helpers: helperPaths,
templates: templates,
resourceSynthesizers: resourceSynthesizers,
projectDescriptionSearchPath: projectDescriptionPath
)

Expand Down
Loading