Skip to content

Commit

Permalink
Adding Writing (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
leogdion committed Jan 2, 2025
1 parent 90521fc commit d8c8bd1
Show file tree
Hide file tree
Showing 45 changed files with 2,234 additions and 614 deletions.
2 changes: 1 addition & 1 deletion .swift-format
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
"prioritizeKeepingFunctionOutputTogether" : false,
"respectsExistingLineBreaks" : true,
"rules" : {
"AllPublicDeclarationsHaveDocumentation" : true,
"AllPublicDeclarationsHaveDocumentation" : false,
"AlwaysUseLiteralForEmptyCollectionInit" : false,
"AlwaysUseLowerCamelCase" : true,
"AmbiguousTrailingClosureOverload" : true,
Expand Down
2 changes: 1 addition & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ opt_in_rules:
- optional_enum_case_matching
- overridden_super_call
- override_in_extension
- pattern_matching_keywords
- prefer_self_type_over_type_of_self
- prefer_zero_over_explicit_init
- private_action
Expand Down Expand Up @@ -117,6 +116,7 @@ identifier_name:
excluded:
- DerivedData
- .build
- Compression.playground
indentation_width:
indentation_width: 2
file_name:
Expand Down
11 changes: 10 additions & 1 deletion Package.resolved
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "3decd9c5eb6868fc5ea969ecd2b6cffa4288c57141e5c04692f90d05d8c01390",
"originHash" : "5c7d79d1516b47d715f10d9564b397b010b1595ee060d86d88874116b92a77e0",
"pins" : [
{
"identity" : "swift-argument-parser",
Expand Down Expand Up @@ -28,6 +28,15 @@
"version" : "1.0.0"
}
},
{
"identity" : "swift-log",
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-log.git",
"state" : {
"revision" : "96a2f8a0fa41e9e09af4585e2724c4e825410b91",
"version" : "1.6.2"
}
},
{
"identity" : "swift-syntax",
"kind" : "remoteSourceControl",
Expand Down
17 changes: 14 additions & 3 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ let package = Package(
dependencies: [
.package(url: "https://github.com/apple/swift-argument-parser.git", from: "1.4.0"),
.package(url: "https://github.com/swiftlang/swift-syntax.git", from: "601.0.0-prerelease-2024-11-18"),
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.4.0")
.package(url: "https://github.com/apple/swift-docc-plugin", from: "1.4.0"),
.package(url: "https://github.com/apple/swift-log.git", from: "1.6.0")
],
targets: [
// Targets are the basic building blocks of a package, defining a module or a test suite.
Expand All @@ -25,14 +26,24 @@ let package = Package(
name: "PackageDSLKit",
dependencies: [
.product(name: "SwiftSyntax", package: "swift-syntax"),
.product(name: "SwiftParser", package: "swift-syntax")
.product(name: "SwiftParser", package: "swift-syntax"),
.product(name: "SwiftSyntaxBuilder", package: "swift-syntax"),
.product(
name: "Logging",
package: "swift-log",
condition: .when(platforms: [.linux, .openbsd, .wasi, .android, .windows])
)
],

resources: [
.copy("Resources/PackageDSL.swift.txt")
]
),
.executableTarget(
name: "package",
dependencies: [
"PackageDSLKit",
.product(name: "ArgumentParser", package: "swift-argument-parser"),
.product(name: "ArgumentParser", package: "swift-argument-parser")
]
),
.testTarget(
Expand Down
8 changes: 4 additions & 4 deletions Sources/PackageDSLKit/Component.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@
// OTHER DEALINGS IN THE SOFTWARE.
//

struct Component {
let name: String
let inheritedTypes: [String]
let properties: [String: Property]
internal struct Component: Sendable {
internal let name: String
internal let inheritedTypes: [String]
internal let properties: [String: Property]
}
29 changes: 27 additions & 2 deletions Sources/PackageDSLKit/ComponentBuildable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,31 @@
// OTHER DEALINGS IN THE SOFTWARE.
//

protocol ComponentBuildable {
init?(component: Component)
import Foundation

internal protocol ComponentBuildable {
associatedtype Requirements = Void
static var directoryName: String { get }
init(component: Component, requirements: Requirements)
static func requirements(from component: Component) -> Requirements?
func createComponent() -> Component
}

extension ComponentBuildable {
internal init?(component: Component) {
guard let requirements = Self.requirements(from: component) else {
return nil
}
self.init(component: component, requirements: requirements)
}

internal static func directoryURL(relativeTo packageDSLURL: URL) -> URL {
packageDSLURL.appending(path: self.directoryName, directoryHint: .isDirectory)
}
}

extension Component {
internal func isType<T: ComponentBuildable>(of type: T.Type) -> Bool {
type.requirements(from: self) != nil
}
}
66 changes: 66 additions & 0 deletions Sources/PackageDSLKit/ComponentWriter.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//
// ComponentWriter.swift
// PackageDSLKit
//
// Created by Leo Dion.
// Copyright © 2025 BrightDigit.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//

import SwiftSyntax

internal struct ComponentWriter {
private let propertyWriter = PropertyWriter()
internal func node(from component: Component) -> StructDeclSyntax {
let memberBlockList = MemberBlockItemListSyntax(
component.properties.values.map(propertyWriter.node(from:)).map {
MemberBlockItemSyntax(decl: $0)
}
)
let inheritedTypes = component.inheritedTypes
.map { TokenSyntax.identifier($0) }
.map {
IdentifierTypeSyntax(name: $0)
}
.map {
InheritedTypeSyntax(type: $0)
}
.reversed()
.enumerated()
.map { index, expression in
if index == 0 {
return expression
}
return expression.with(\.trailingComma, .commaToken())
}
.reversed()
let inheritedTypeList = InheritedTypeListSyntax(inheritedTypes)
let clause = InheritanceClauseSyntax(inheritedTypes: inheritedTypeList)
let memberBlock = MemberBlockSyntax(members: memberBlockList)
return StructDeclSyntax(
name: .identifier(component.name, leadingTrivia: .space),
inheritanceClause: clause,
memberBlock: memberBlock
)
}
}
80 changes: 80 additions & 0 deletions Sources/PackageDSLKit/Dependency+ComponentBuildable.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//
// Dependency+ComponentBuildable.swift
// PackageDSLKit
//
// Created by Leo Dion.
// Copyright © 2025 BrightDigit.
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the “Software”), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//

extension Dependency: ComponentBuildable {
internal typealias Requirements = DependencyType
public static let directoryName: String = "Dependencies"

internal init(component: Component, requirements: Requirements) {
let package =
(component.properties["dependencies"]?.code.first?.filter({ character in
character.isLetter || character.isNumber
})).map(DependencyRef.init)

self.init(
typeName: component.name,
type: requirements,
dependency: component.properties["dependency"]?.code.first,
package: package
)
}

internal static func requirements(from component: Component) -> DependencyType? {
guard let dependencyType = DependencyType(strings: component.inheritedTypes) else {
return nil
}
guard dependencyType.rawValue > 0 else {
return nil
}
return dependencyType
}

internal func createComponent() -> Component {
var properties = [String: Property]()
let inheritedTypes: [String]
let name: String

name = typeName
inheritedTypes = self.type.asInheritedTypes()

if let dependency {
properties["dependency"] = Property(
name: "dependency", type: "Package.Dependency", code: [dependency]
)
}

if let package {
properties["package"] = Property(
name: "package", type: "PackageDependency", code: [package.asFunctionCall()]
)
}

return .init(name: name, inheritedTypes: inheritedTypes, properties: properties)
}
}
55 changes: 44 additions & 11 deletions Sources/PackageDSLKit/Dependency.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,18 @@
//

public struct Dependency: TypeSource {
public let typeName: String

public struct DependencyType: OptionSet, Sendable {
public init(rawValue: Int) {
self.rawValue = rawValue
}

public var rawValue: Int

public typealias RawValue = Int

public static let package = DependencyType(rawValue: 1)
public static let target = DependencyType(rawValue: 2)

private static let strings: [String] = ["PackageDependency", "TargetDependency"]

public var rawValue: Int
public init(rawValue: Int) {
self.rawValue = rawValue
}
public init?(strings: [String]) {
let indicies = strings.map {
Self.strings.firstIndex(of: $0)
Expand All @@ -55,9 +52,45 @@ public struct Dependency: TypeSource {
let rawValue = rawValues.reduce(0) { $0 + $1 }
self.init(rawValue: rawValue)
}

internal func asInheritedTypes() -> [String] {
rawValue.powerOfTwoExponents().map { Self.strings[$0] }
}
}

let type: DependencyType
let dependency: String?
let package: DependencyRef?
public let typeName: String

public let type: DependencyType
public let dependency: String?
public let package: DependencyRef?

public init(
typeName: String,
type: Dependency.DependencyType,
dependency: String? = nil,
package: DependencyRef? = nil
) {
self.typeName = typeName
self.type = type
self.dependency = dependency
self.package = package
}
}

extension Int {
fileprivate func powerOfTwoExponents() -> [Int] {
var number = self
var exponents: [Int] = []
var currentExponent = 0

while number > 0 {
if number & 1 == 1 {
exponents.append(currentExponent)
}
number >>= 1
currentExponent += 1
}

return exponents
}
}
2 changes: 1 addition & 1 deletion Sources/PackageDSLKit/ImportDeclSyntax.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import SwiftSyntax

extension ImportDeclSyntax {
static func module(_ moduleName: String) -> ImportDeclSyntax {
internal static func module(_ moduleName: String) -> ImportDeclSyntax {
ImportDeclSyntax(
path: ImportPathComponentListSyntax([
ImportPathComponentSyntax(
Expand Down
16 changes: 9 additions & 7 deletions Sources/PackageDSLKit/Index.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,14 @@
// OTHER DEALINGS IN THE SOFTWARE.
//

import SwiftSyntax

public struct Index {
public let entries: [EntryRef]
public let dependencies: [DependencyRef]
public let testTargets: [TestTargetRef]
public let swiftSettings: [SwiftSettingRef]
public let modifiers: [Modifier]
public init(
entries: [EntryRef],
dependencies: [DependencyRef],
Expand All @@ -41,17 +48,12 @@ public struct Index {
self.swiftSettings = swiftSettings
self.modifiers = modifiers
}

public let entries: [EntryRef]
public let dependencies: [DependencyRef]
public let testTargets: [TestTargetRef]
public let swiftSettings: [SwiftSettingRef]
public let modifiers: [Modifier]
}

extension Index {
internal init(
items: [(PackageIndexStrategy.ExpressionKind, String)], modifiers: [ModifierType: [String]]
items: [(PackageIndexStrategy.ExpressionKind, String)],
modifiers: [ModifierType: [String]]
) {
var entries: [EntryRef] = []
var dependencies: [DependencyRef] = []
Expand Down
Loading

0 comments on commit d8c8bd1

Please sign in to comment.