diff --git a/Package.resolved b/Package.resolved index fb51d24..45337e9 100644 --- a/Package.resolved +++ b/Package.resolved @@ -14,8 +14,8 @@ "kind" : "remoteSourceControl", "location" : "https://github.com/swiftlang/swift-syntax.git", "state" : { - "revision" : "cb53fa1bd3219b0b23ded7dfdd3b2baff266fd25", - "version" : "600.0.0" + "revision" : "0687f71944021d616d34d922343dcef086855920", + "version" : "600.0.1" } }, { diff --git a/Sources/CodableToTypeScript/Generator/PackageGenerator.swift b/Sources/CodableToTypeScript/Generator/PackageGenerator.swift index 89f733e..5de8b75 100644 --- a/Sources/CodableToTypeScript/Generator/PackageGenerator.swift +++ b/Sources/CodableToTypeScript/Generator/PackageGenerator.swift @@ -87,7 +87,10 @@ public final class PackageGenerator { try withErrorCollector { collect in while let source = targetSources.popLast() { - generatedSources.insert(source) + guard generatedSources.insert(source).inserted else { + continue + } + collect(at: source.file.lastPathComponent) { let tsSource = try convertedSources[source] ?? (codeGenerator.convert(source: source)) @@ -96,23 +99,25 @@ public final class PackageGenerator { source: tsSource ) try didConvertSource?(source, entry) + if entry.isEmpty { + return + } + + generatedEntries.append(.init( + file: entry.file, + source: entry.source + )) - if !entry.source.elements.isEmpty { - generatedEntries.append(.init( - file: entry.file, - source: entry.source - )) - - let imports = try tsSource.buildAutoImportDecls( - from: entry.file, - symbolTable: allSymbols, - fileExtension: importFileExtension - ) - tsSource.replaceImportDecls(imports) - for importedDecl in imports.flatMap(\.names) { - if let source = symbolToSource[importedDecl], !generatedSources.contains(source) { - targetSources.append(source) - } + let imports = try tsSource.buildAutoImportDecls( + from: entry.file, + symbolTable: allSymbols, + fileExtension: importFileExtension + ) + tsSource.replaceImportDecls(imports) + for importedSymbolName in imports.flatMap(\.names) { + // Add a file that is used but not included in the generation target + if let source = symbolToSource[importedSymbolName], !generatedSources.contains(source) { + targetSources.append(source) } } } @@ -166,3 +171,9 @@ public final class PackageGenerator { } } #endif + +extension PackageEntry { + fileprivate var isEmpty: Bool { + source.elements.isEmpty + } +} diff --git a/Tests/CodableToTypeScriptTests/PackageGeneratorTests.swift b/Tests/CodableToTypeScriptTests/PackageGeneratorTests.swift index d7e86a7..6751534 100644 --- a/Tests/CodableToTypeScriptTests/PackageGeneratorTests.swift +++ b/Tests/CodableToTypeScriptTests/PackageGeneratorTests.swift @@ -148,4 +148,44 @@ final class PackageGeneratorTests: XCTestCase { }) XCTAssertFalse(hasTSAbsoluteURL) } + + func testGenerationsNotDuplicates() throws { + let context = Context() + + let aModule = Reader( + context: context, + module: context.getOrCreateModule(name: "A") + ).read(source: """ + struct A: Codable {} + """, file: URL(fileURLWithPath: "A.swift")).module + + let bModule = Reader( + context: context, + module: context.getOrCreateModule(name: "B") + ).read(source: """ + import A + + struct B: Codable { + var a: A + } + """, file: URL(fileURLWithPath: "B.swift")).module + + let generator = PackageGenerator( + context: context, + symbols: SymbolTable(), + importFileExtension: .js, + outputDirectory: URL(fileURLWithPath: "/dev/null", isDirectory: true) + ) + + var convertedEntries: [PackageEntry] = [] + generator.didConvertSource = { (source, entry) in + convertedEntries.append(entry) + } + _ = try generator.generate(modules: [aModule, bModule]) // the order is important! + + XCTAssertEqual(convertedEntries.map(\.file.lastPathComponent), [ + "B.ts", + "A.ts", + ]) + } }