From adfd8b3a38579fa205970471877477ebc80a513e Mon Sep 17 00:00:00 2001 From: devyhan Date: Mon, 17 Oct 2022 18:58:43 +0900 Subject: [PATCH 1/4] fix: ResourceSynthesizers folder not added on edit --- Gemfile.lock | 36 +++++------ .../ProjectEditor/ProjectEditor.swift | 11 +++- .../ProjectEditor/ProjectEditorMapper.swift | 16 +++++ .../ResourceSynthesizerPathLocator.swift | 23 +++++-- .../MockResourceSynthesizerPathLocator.swift | 5 ++ ...ourceSynthesizer+ManifestMapperTests.swift | 61 ++++++++++++++++++- 6 files changed, 127 insertions(+), 25 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index c29ef162953..6aeda70a96a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,24 +3,25 @@ GEM specs: CFPropertyList (3.0.5) rexml - actionpack (7.0.4) - actionview (= 7.0.4) - activesupport (= 7.0.4) - rack (~> 2.0, >= 2.2.0) + actionpack (6.1.7) + actionview (= 6.1.7) + activesupport (= 6.1.7) + rack (~> 2.0, >= 2.0.9) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actionview (7.0.4) - activesupport (= 7.0.4) + actionview (6.1.7) + activesupport (= 6.1.7) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activesupport (7.0.4) + activesupport (6.1.7) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) + zeitwerk (~> 2.3) addressable (2.8.1) public_suffix (>= 2.0.2, < 6.0) ansi (1.5.0) @@ -131,7 +132,6 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2022.0105) mini_mime (1.1.2) - mini_portile2 (2.8.0) minitest (5.16.3) minitest-reporters (1.5.0) ansi @@ -143,8 +143,9 @@ GEM multi_test (0.1.2) nanaimo (0.3.0) naturally (2.2.1) - nokogiri (1.13.8) - mini_portile2 (~> 2.8.0) + nokogiri (1.13.8-arm64-darwin) + racc (~> 1.4) + nokogiri (1.13.8-x86_64-darwin) racc (~> 1.4) octokit (4.25.1) faraday (>= 1, < 3) @@ -168,13 +169,12 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.4.3) loofah (~> 2.3) - railties (7.0.4) - actionpack (= 7.0.4) - activesupport (= 7.0.4) + railties (6.1.7) + actionpack (= 6.1.7) + activesupport (= 6.1.7) method_source rake (>= 12.2) thor (~> 1.0) - zeitwerk (~> 2.5) rainbow (3.1.1) rake (13.0.6) regexp_parser (2.6.0) @@ -216,8 +216,8 @@ GEM rubocop-rails (~> 2.0) rubocop-rake (0.5.1) rubocop - rubocop-shopify (2.10.1) - rubocop (~> 1.35) + rubocop-shopify (2.5.0) + rubocop (~> 1.25) ruby-macho (1.4.0) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) @@ -254,7 +254,7 @@ GEM zeitwerk (2.6.1) PLATFORMS - ruby + universal-darwin-21 DEPENDENCIES byebug (~> 11.1) @@ -286,4 +286,4 @@ DEPENDENCIES zeitwerk (~> 2.4) BUNDLED WITH - 2.2.33 + 2.3.23 diff --git a/Sources/TuistKit/ProjectEditor/ProjectEditor.swift b/Sources/TuistKit/ProjectEditor/ProjectEditor.swift index beb423f144a..a5ab036c1a6 100644 --- a/Sources/TuistKit/ProjectEditor/ProjectEditor.swift +++ b/Sources/TuistKit/ProjectEditor/ProjectEditor.swift @@ -59,6 +59,8 @@ final class ProjectEditor: ProjectEditing { /// Utility to locate the custom templates directory let templatesDirectoryLocator: TemplatesDirectoryLocating + + let resourceSynthesizersDirectoryLocator: ResourceSynthesizerPathLocating private let cacheDirectoryProviderFactory: CacheDirectoriesProviderFactoring private let projectDescriptionHelpersBuilderFactory: ProjectDescriptionHelpersBuilderFactoring @@ -74,6 +76,7 @@ final class ProjectEditor: ProjectEditing { helpersDirectoryLocator: HelpersDirectoryLocating = HelpersDirectoryLocator(), writer: XcodeProjWriting = XcodeProjWriter(), templatesDirectoryLocator: TemplatesDirectoryLocating = TemplatesDirectoryLocator(), + resourceSynthesizersDirectoryLocator: ResourceSynthesizerPathLocating = ResourceSynthesizerPathLocator(), cacheDirectoryProviderFactory: CacheDirectoriesProviderFactoring = CacheDirectoriesProviderFactory(), projectDescriptionHelpersBuilderFactory: ProjectDescriptionHelpersBuilderFactoring = ProjectDescriptionHelpersBuilderFactory() @@ -85,6 +88,7 @@ final class ProjectEditor: ProjectEditing { self.helpersDirectoryLocator = helpersDirectoryLocator self.writer = writer self.templatesDirectoryLocator = templatesDirectoryLocator + self.resourceSynthesizersDirectoryLocator = resourceSynthesizersDirectoryLocator self.cacheDirectoryProviderFactory = cacheDirectoryProviderFactory self.projectDescriptionHelpersBuilderFactory = projectDescriptionHelpersBuilderFactory } @@ -134,6 +138,10 @@ final class ProjectEditor: ProjectEditing { let templates = templatesDirectoryLocator.locateUserTemplates(at: editingPath).map { 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, @@ -149,7 +157,7 @@ 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) } @@ -169,6 +177,7 @@ final class ProjectEditor: ProjectEditing { pluginProjectDescriptionHelpersModule: builtPluginHelperModules, helpers: helpers, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath.parentDirectory ) diff --git a/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift b/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift index 08578ca95ec..d8f09100ab5 100644 --- a/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift +++ b/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift @@ -18,6 +18,7 @@ protocol ProjectEditorMapping: AnyObject { pluginProjectDescriptionHelpersModule: [ProjectDescriptionHelpersModule], helpers: [AbsolutePath], templates: [AbsolutePath], + resourceSynthesizers: [AbsolutePath], projectDescriptionSearchPath: AbsolutePath ) throws -> Graph } @@ -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() @@ -59,6 +61,7 @@ final class ProjectEditorMapper: ProjectEditorMapping { tuistPath: tuistPath, helpers: helpers, templates: templates, + resourceSynthesizers: resourceSynthesizers, configPath: configPath, dependenciesPath: dependenciesPath, editablePluginTargets: editablePluginManifests.map(\.name), @@ -131,6 +134,7 @@ final class ProjectEditorMapper: ProjectEditorMapping { tuistPath: AbsolutePath, helpers: [AbsolutePath], templates: [AbsolutePath], + resourceSynthesizers: [AbsolutePath], configPath: AbsolutePath?, dependenciesPath: AbsolutePath?, editablePluginTargets: [String], @@ -193,6 +197,17 @@ final class ProjectEditorMapper: ProjectEditorMapping { dependencies: helpersTarget.flatMap { [TargetDependency.target(name: $0.name)] } ?? [] ) }() + + 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 @@ -221,6 +236,7 @@ final class ProjectEditorMapper: ProjectEditorMapping { let targets = [ helpersTarget, templatesTarget, + resourceSynthesizersTarget, configTarget, dependenciesTarget, ] diff --git a/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift b/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift index eb7e7efe4dd..ad2846d59de 100644 --- a/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift +++ b/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift @@ -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, @@ -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] @@ -67,7 +69,7 @@ final class ResourceSynthesizerPathLocator: ResourceSynthesizerPathLocating { return resourceTemplatePath } - func templatePath( + public func templatePath( for resourceName: String, path: AbsolutePath ) -> AbsolutePath? { @@ -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 + } } diff --git a/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift b/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift index a8728e882c8..c179a0be29c 100644 --- a/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift +++ b/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift @@ -6,6 +6,7 @@ import TuistGraph public final class MockResourceSynthesizerPathLocator: ResourceSynthesizerPathLocating { public init() {} + public var locateStub: ((AbsolutePath) -> AbsolutePath?)? public var templatePathStub: ((String, String, [PluginResourceSynthesizer]) throws -> AbsolutePath)? public func templatePath( for pluginName: String, @@ -22,4 +23,8 @@ public final class MockResourceSynthesizerPathLocator: ResourceSynthesizerPathLo ) -> AbsolutePath? { templatePathResourceStub?(resourceName, path) } + + public func locate(at: TSCBasic.AbsolutePath) -> TSCBasic.AbsolutePath? { + locateStub?(at) + } } diff --git a/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift b/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift index 8a6a1854cc6..89a07928953 100644 --- a/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift +++ b/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift @@ -11,16 +11,18 @@ import XCTest final class ResourceSynthesizerManifestMapperTests: TuistUnitTestCase { private var resourceSynthesizerPathLocator: MockResourceSynthesizerPathLocator! + var subject: ResourceSynthesizerPathLocator! override func setUp() { super.setUp() resourceSynthesizerPathLocator = MockResourceSynthesizerPathLocator() + subject = ResourceSynthesizerPathLocator(rootDirectoryLocator: RootDirectoryLocator()) } override func tearDown() { resourceSynthesizerPathLocator = nil - + subject = nil super.tearDown() } @@ -123,4 +125,61 @@ final class ResourceSynthesizerManifestMapperTests: TuistUnitTestCase { [.test(name: "Plugin")] ) } + + func test_locate_when_a_resourceSynthesizer_and_git_directory_exists() throws { + // Given + let resourceSynthesizerDirectory = try temporaryPath() + try createFolders(["this/is/a/very/nested/directory", "this/is/Tuist/ResourceSynthesizers", "this/.git"]) + + // When + let got = subject.locate(at: resourceSynthesizerDirectory.appending(RelativePath("this/is/a/very/nested/directory"))) + + // Then + XCTAssertEqual(got, resourceSynthesizerDirectory.appending(RelativePath("this/is/Tuist/ResourceSynthesizers"))) + } + + func test_locate_when_a_resourceSynthesizer_directory_exists() throws { + // Given + let resourceSynthesizerDirectory = try temporaryPath() + try createFolders(["this/is/a/very/nested/directory", "this/is/Tuist/ResourceSynthesizers"]) + + // When + let got = subject.locate(at: resourceSynthesizerDirectory.appending(RelativePath("this/is/a/very/nested/directory"))) + + // Then + XCTAssertEqual(got, resourceSynthesizerDirectory.appending(RelativePath("this/is/Tuist/ResourceSynthesizers"))) + } + + func test_locate_when_a_git_directory_exists() throws { + // Given + let resourceSynthesizerDirectory = try temporaryPath() + try createFolders(["this/is/a/very/nested/directory", "this/.git", "this/Tuist/ResourceSynthesizers"]) + + // When + let got = subject.locate(at: resourceSynthesizerDirectory.appending(RelativePath("this/is/a/very/nested/directory"))) + + // Then + XCTAssertEqual(got, resourceSynthesizerDirectory.appending(RelativePath("this/Tuist/ResourceSynthesizers"))) + } + + func test_locate_when_multiple_tuist_directories_exists() throws { + // Given + let resourceSynthesizerDirectory = try temporaryPath() + try createFolders(["this/is/a/very/nested/Tuist/ResourceSynthesizers", "this/is/Tuist/ResourceSynthesizers"]) + let paths = [ + "this/is/a/very/directory", + "this/is/a/very/nested/directory", + ] + + // When + let got = paths.map { + subject.locate(at: resourceSynthesizerDirectory.appending(RelativePath($0))) + } + + // Then + XCTAssertEqual(got, [ + "this/is/Tuist/ResourceSynthesizers", + "this/is/a/very/nested/Tuist/ResourceSynthesizers", + ].map { resourceSynthesizerDirectory.appending(RelativePath($0)) }) + } } From 5c561f6fa8c73f5bfa87fab5f42437cd669e322e Mon Sep 17 00:00:00 2001 From: devyhan Date: Mon, 17 Oct 2022 21:57:24 +0900 Subject: [PATCH 2/4] Fixed based on PR review feedback --- Gemfile.lock | 36 +++++++++---------- .../ProjectEditor/ProjectEditor.swift | 1 + .../MockResourceSynthesizerPathLocator.swift | 2 +- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6aeda70a96a..a71837d7452 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,25 +3,24 @@ GEM specs: CFPropertyList (3.0.5) rexml - actionpack (6.1.7) - actionview (= 6.1.7) - activesupport (= 6.1.7) - rack (~> 2.0, >= 2.0.9) + actionpack (7.0.4) + actionview (= 7.0.4) + activesupport (= 7.0.4) + rack (~> 2.0, >= 2.2.0) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.2.0) - actionview (6.1.7) - activesupport (= 6.1.7) + actionview (7.0.4) + activesupport (= 7.0.4) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) - activesupport (6.1.7) + activesupport (7.0.4) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) - zeitwerk (~> 2.3) addressable (2.8.1) public_suffix (>= 2.0.2, < 6.0) ansi (1.5.0) @@ -132,6 +131,7 @@ GEM mime-types-data (~> 3.2015) mime-types-data (3.2022.0105) mini_mime (1.1.2) + mini_portile2 (2.8.0) minitest (5.16.3) minitest-reporters (1.5.0) ansi @@ -143,9 +143,8 @@ GEM multi_test (0.1.2) nanaimo (0.3.0) naturally (2.2.1) - nokogiri (1.13.8-arm64-darwin) - racc (~> 1.4) - nokogiri (1.13.8-x86_64-darwin) + nokogiri (1.13.8) + mini_portile2 (~> 2.8.0) racc (~> 1.4) octokit (4.25.1) faraday (>= 1, < 3) @@ -169,12 +168,13 @@ GEM nokogiri (>= 1.6) rails-html-sanitizer (1.4.3) loofah (~> 2.3) - railties (6.1.7) - actionpack (= 6.1.7) - activesupport (= 6.1.7) + railties (7.0.4) + actionpack (= 7.0.4) + activesupport (= 7.0.4) method_source rake (>= 12.2) thor (~> 1.0) + zeitwerk (~> 2.5) rainbow (3.1.1) rake (13.0.6) regexp_parser (2.6.0) @@ -216,8 +216,8 @@ GEM rubocop-rails (~> 2.0) rubocop-rake (0.5.1) rubocop - rubocop-shopify (2.5.0) - rubocop (~> 1.25) + rubocop-shopify (2.10.1) + rubocop (~> 1.35) ruby-macho (1.4.0) ruby-progressbar (1.11.0) ruby2_keywords (0.0.5) @@ -254,7 +254,7 @@ GEM zeitwerk (2.6.1) PLATFORMS - universal-darwin-21 + ruby DEPENDENCIES byebug (~> 11.1) @@ -286,4 +286,4 @@ DEPENDENCIES zeitwerk (~> 2.4) BUNDLED WITH - 2.3.23 + 2.2.33 \ No newline at end of file diff --git a/Sources/TuistKit/ProjectEditor/ProjectEditor.swift b/Sources/TuistKit/ProjectEditor/ProjectEditor.swift index a5ab036c1a6..31cab47b20d 100644 --- a/Sources/TuistKit/ProjectEditor/ProjectEditor.swift +++ b/Sources/TuistKit/ProjectEditor/ProjectEditor.swift @@ -60,6 +60,7 @@ final class ProjectEditor: ProjectEditing { /// Utility to locate the custom templates directory let templatesDirectoryLocator: TemplatesDirectoryLocating + /// Utility to locate the resource synthesizers directory let resourceSynthesizersDirectoryLocator: ResourceSynthesizerPathLocating private let cacheDirectoryProviderFactory: CacheDirectoriesProviderFactoring diff --git a/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift b/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift index c179a0be29c..0c90b5e27b1 100644 --- a/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift +++ b/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift @@ -6,7 +6,6 @@ import TuistGraph public final class MockResourceSynthesizerPathLocator: ResourceSynthesizerPathLocating { public init() {} - public var locateStub: ((AbsolutePath) -> AbsolutePath?)? public var templatePathStub: ((String, String, [PluginResourceSynthesizer]) throws -> AbsolutePath)? public func templatePath( for pluginName: String, @@ -24,6 +23,7 @@ public final class MockResourceSynthesizerPathLocator: ResourceSynthesizerPathLo templatePathResourceStub?(resourceName, path) } + public var locateStub: ((AbsolutePath) -> AbsolutePath?)? public func locate(at: TSCBasic.AbsolutePath) -> TSCBasic.AbsolutePath? { locateStub?(at) } From b86f899790857f83832ffa4cd6bf747a34abd929 Mon Sep 17 00:00:00 2001 From: devyhan Date: Mon, 17 Oct 2022 22:35:54 +0900 Subject: [PATCH 3/4] chore: linting --- Sources/TuistKit/ProjectEditor/ProjectEditor.swift | 8 +++++--- Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift | 2 +- .../Utils/ResourceSynthesizerPathLocator.swift | 6 +++--- .../Utils/Mocks/MockResourceSynthesizerPathLocator.swift | 2 +- .../ResourceSynthesizer+ManifestMapperTests.swift | 2 +- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Sources/TuistKit/ProjectEditor/ProjectEditor.swift b/Sources/TuistKit/ProjectEditor/ProjectEditor.swift index 31cab47b20d..0c3be98a73b 100644 --- a/Sources/TuistKit/ProjectEditor/ProjectEditor.swift +++ b/Sources/TuistKit/ProjectEditor/ProjectEditor.swift @@ -59,7 +59,7 @@ final class ProjectEditor: ProjectEditing { /// Utility to locate the custom templates directory let templatesDirectoryLocator: TemplatesDirectoryLocating - + /// Utility to locate the resource synthesizers directory let resourceSynthesizersDirectoryLocator: ResourceSynthesizerPathLocating @@ -139,7 +139,7 @@ final class ProjectEditor: ProjectEditing { let templates = templatesDirectoryLocator.locateUserTemplates(at: editingPath).map { 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") } ?? [] @@ -158,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, resourceSynthesizers.isEmpty { + if projectManifests.isEmpty, editablePluginManifests.isEmpty, helpers.isEmpty, templates.isEmpty, + resourceSynthesizers.isEmpty + { throw ProjectEditorError.noEditableFiles(editingPath) } diff --git a/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift b/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift index d8f09100ab5..32f6590f7a1 100644 --- a/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift +++ b/Sources/TuistKit/ProjectEditor/ProjectEditorMapper.swift @@ -197,7 +197,7 @@ final class ProjectEditorMapper: ProjectEditorMapping { dependencies: helpersTarget.flatMap { [TargetDependency.target(name: $0.name)] } ?? [] ) }() - + let resourceSynthesizersTarget: Target? = { guard !resourceSynthesizers.isEmpty else { return nil } return editorHelperTarget( diff --git a/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift b/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift index ad2846d59de..7bfbe0b1fcb 100644 --- a/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift +++ b/Sources/TuistLoader/Utils/ResourceSynthesizerPathLocator.swift @@ -6,7 +6,7 @@ import TuistSupport public protocol ResourceSynthesizerPathLocating { func locate(at: AbsolutePath) -> AbsolutePath? - + func templatePath( for pluginName: String, resourceName: String, @@ -82,9 +82,9 @@ public final class ResourceSynthesizerPathLocator: ResourceSynthesizerPathLocati ) 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 diff --git a/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift b/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift index 0c90b5e27b1..d12b8915930 100644 --- a/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift +++ b/Sources/TuistLoaderTesting/Utils/Mocks/MockResourceSynthesizerPathLocator.swift @@ -22,7 +22,7 @@ public final class MockResourceSynthesizerPathLocator: ResourceSynthesizerPathLo ) -> AbsolutePath? { templatePathResourceStub?(resourceName, path) } - + public var locateStub: ((AbsolutePath) -> AbsolutePath?)? public func locate(at: TSCBasic.AbsolutePath) -> TSCBasic.AbsolutePath? { locateStub?(at) diff --git a/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift b/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift index 89a07928953..7897ff1754e 100644 --- a/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift +++ b/Tests/TuistLoaderTests/Models+ManifestMappers/ResourceSynthesizer+ManifestMapperTests.swift @@ -125,7 +125,7 @@ final class ResourceSynthesizerManifestMapperTests: TuistUnitTestCase { [.test(name: "Plugin")] ) } - + func test_locate_when_a_resourceSynthesizer_and_git_directory_exists() throws { // Given let resourceSynthesizerDirectory = try temporaryPath() From 55531b6ba644f69695122227d016ea29e74ee269 Mon Sep 17 00:00:00 2001 From: devyhan Date: Tue, 18 Oct 2022 01:00:30 +0900 Subject: [PATCH 4/4] fix: Changes caused by adding the ProjectEditorMapper model - Add resourceSynthesizers to graph in ProjectEditorMapperTests.swift - By adding resourceSynthesizers, Increase graph target count in test_edit_when_there_are_helpers_and_setup_and_config_and_dependencies_and_tasks_and_plugins() 7 -> 8 --- .../Mocks/MockProjectEditorMapper.swift | 3 ++ .../ProjectEditorMapperTests.swift | 33 ++++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/Tests/TuistKitTests/ProjectEditor/Mocks/MockProjectEditorMapper.swift b/Tests/TuistKitTests/ProjectEditor/Mocks/MockProjectEditorMapper.swift index cd5e7d860f3..2ea3ead1f34 100644 --- a/Tests/TuistKitTests/ProjectEditor/Mocks/MockProjectEditorMapper.swift +++ b/Tests/TuistKitTests/ProjectEditor/Mocks/MockProjectEditorMapper.swift @@ -22,6 +22,7 @@ final class MockProjectEditorMapper: ProjectEditorMapping { pluginProjectDescriptionHelpersModule: [ProjectDescriptionHelpersModule], helpers: [AbsolutePath], templates: [AbsolutePath], + resourceSynthesizers: [AbsolutePath], projectDescriptionPath: AbsolutePath )] = [] @@ -37,6 +38,7 @@ final class MockProjectEditorMapper: ProjectEditorMapping { pluginProjectDescriptionHelpersModule: [ProjectDescriptionHelpersModule], helpers: [AbsolutePath], templates: [AbsolutePath], + resourceSynthesizers: [AbsolutePath], projectDescriptionSearchPath: AbsolutePath ) throws -> Graph { mapArgs.append(( @@ -51,6 +53,7 @@ final class MockProjectEditorMapper: ProjectEditorMapping { pluginProjectDescriptionHelpersModule: pluginProjectDescriptionHelpersModule, helpers: helpers, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionPath: projectDescriptionSearchPath )) diff --git a/Tests/TuistKitTests/ProjectEditor/ProjectEditorMapperTests.swift b/Tests/TuistKitTests/ProjectEditor/ProjectEditorMapperTests.swift index 0aa76364157..eaf56e440c6 100644 --- a/Tests/TuistKitTests/ProjectEditor/ProjectEditorMapperTests.swift +++ b/Tests/TuistKitTests/ProjectEditor/ProjectEditorMapperTests.swift @@ -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" @@ -55,6 +56,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase { pluginProjectDescriptionHelpersModule: [], helpers: helperPaths, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath ) @@ -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 })) @@ -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)) @@ -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" @@ -205,6 +225,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase { pluginProjectDescriptionHelpersModule: [], helpers: helperPaths, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath ) @@ -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" @@ -284,6 +306,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase { pluginProjectDescriptionHelpersModule: [], helpers: helperPaths, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath ) @@ -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" @@ -389,6 +413,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase { pluginProjectDescriptionHelpersModule: [], helpers: helperPaths, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath ) @@ -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" @@ -466,6 +492,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase { pluginProjectDescriptionHelpersModule: [], helpers: helperPaths, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath ) @@ -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([ @@ -577,6 +605,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase { pluginProjectDescriptionHelpersModule: [], helpers: helperPaths, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath ) @@ -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" @@ -618,6 +648,7 @@ final class ProjectEditorMapperTests: TuistUnitTestCase { pluginProjectDescriptionHelpersModule: [remotePlugin], helpers: helperPaths, templates: templates, + resourceSynthesizers: resourceSynthesizers, projectDescriptionSearchPath: projectDescriptionPath )