diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..8082f0c --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,53 @@ +--- +name: Tests + +on: + workflow_call: + pull_request: + +jobs: + yamllint: + runs-on: ubuntu-latest + steps: + - name: Check Out Sources + uses: actions/checkout@v2 + with: + submodules: true + - name: Lint yml files + uses: ibiqlik/action-yamllint@v3 + with: + strict: true + markdownlint: + runs-on: ubuntu-latest + steps: + - name: Check Out Sources + uses: actions/checkout@v2 + - name: Set up Ruby + uses: ruby/setup-ruby@359bebbc29cbe6c87da6bc9ea3bc930432750108 + with: + ruby-version: '3.1' + - name: Install mdl + run: gem install mdl + - name: Lint files + run: mdl . + unittests: + runs-on: macOS-latest + steps: + - name: Checkout Repository + uses: actions/checkout@v2 + with: + submodules: true + - name: Test Swift Framework + run: swift test + swiftlint: + runs-on: ubuntu-latest + steps: + - name: Check Out Sources + uses: actions/checkout@v2 + with: + submodules: true + - name: Lint Files + uses: norio-nomura/action-swiftlint@3.2.1 + with: + args: --strict +... diff --git a/.mdlrc b/.mdlrc new file mode 100644 index 0000000..6df74ff --- /dev/null +++ b/.mdlrc @@ -0,0 +1 @@ +rules "~MD033", "~MD013", "~MD019", "~MD007", "~MD024", "~MD001" \ No newline at end of file diff --git a/.swiftlint.yml b/.swiftlint.yml new file mode 100644 index 0000000..3680228 --- /dev/null +++ b/.swiftlint.yml @@ -0,0 +1,91 @@ +--- +line_length: + warning: 160 + error: 180 + ignores_function_declarations: true + ignores_comments: true + ignores_urls: true +function_body_length: + warning: 150 + error: 200 +function_parameter_count: + warning: 6 + error: 8 +type_body_length: + warning: 250 + error: 300 +file_length: + warning: 300 + error: 500 + ignore_comment_only_lines: true +cyclomatic_complexity: 12 + +opt_in_rules: + - opening_brace + - trailing_semicolon + - toggle_bool + - cyclomatic_complexity + - type_name + - unneeded_parentheses_in_closure_argument + - yoda_condition + - unavailable_function + - nesting + - anyobject_protocol + - array_init + - closure_end_indentation + - closure_spacing + - attributes + - empty_count + - empty_string + - contains_over_first_not_nil + - convenience_type + - discouraged_object_literal + - explicit_init + - fallthrough + - first_where + - implicit_return + - private_action + - private_outlet + - multiline_function_chains + - multiline_parameters + - line_length + - override_in_extension + - overridden_super_call + - identical_operands + - lower_acl_than_parent + - multiline_arguments + - number_separator + - operator_usage_whitespace + - pattern_matching_keywords + - sorted_first_last + - sorted_imports + - prohibited_super_call + - redundant_nil_coalescing + - single_test_class + - weak_delegate + - function_default_parameter_at_end + - large_tuple + - discouraged_optional_boolean + - literal_expression_end_indentation + - no_extension_access_modifier + - trailing_whitespace + - switch_case_alignment + - trailing_comma + - joined_default_parameter + - trailing_newline + - return_arrow_whitespace + - syntactic_sugar + - comma + - colon + - force_cast + - force_try + - force_unwrapping + +disabled_rules: + - todo + - private_over_fileprivate + - discouraged_optional_collection + - let_var_whitespace + - identifier_name + - implicitly_unwrapped_optional +... diff --git a/.yamllint b/.yamllint new file mode 100644 index 0000000..8660c03 --- /dev/null +++ b/.yamllint @@ -0,0 +1,9 @@ +--- +extends: default + +rules: + line-length: + max: 100 + level: error + truthy: disable +... diff --git a/README.md b/README.md index 475cd46..8228193 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # DependencyGraph -A lightweight, type‑safe library for modeling and resolving directed acyclic graphs (DAGs) of dependencies. +A lightweight, type‑safe library for modeling and resolving directed acyclic graphs (DAGs) of dependencies. It provides a simple API to define nodes, establish relationships, and automatically compute an execution order that respects all dependencies. --- @@ -48,9 +48,9 @@ swift build ### Xcode 1. Open your project. -2. Choose **File → Swift Packages → Add Package Dependency…** -3. Enter the URL `https://github.com/P0rc3lain/DependencyGraph.git` and select the desired version. -4. Add the library target to your target’s **Dependencies**. +1. Choose **File → Swift Packages → Add Package Dependency…**. +1. Enter the URL `https://github.com/P0rc3lain/DependencyGraph.git` and select the desired version. +1. Add the library target to your target’s **Dependencies**. --- @@ -60,23 +60,23 @@ swift build import DependencyGraph // 1️⃣ Define nodes (any hashable type) -let a = Node(id: "A") -let b = Node(id: "B") -let c = Node(id: "C") +let graph = PNGraph() +let a = graph.add(identifier: "A") +let b = graph.add(identifier: "B") +let c = graph.add(identifier: "C") +let d = graph.add(identifier: "D") +let e = graph.add(identifier: "E") // 2️⃣ Build the graph -let graph = Graph() -graph.add(node: a) -graph.add(node: b) -graph.add(node: c) - -graph.addDependency(source: a, destination: b) // A → B -graph.addDependency(source: b, destination: c) // B → C -graph.addDependency(source: a, destination: c) // A → C (optional) +b.addDependency(node: a) +c.addDependency(node: b) +d.addDependency(node: b) +e.addDependency(node: a) +b.addDependency(node: e) // 3️⃣ Resolve execution order -if let order = graph.resolve() { - print("Execution order: \(order.map { $0.id })") +if let order = try? graph.compile() { + print("Execution order: \(order.map { $0 })") } else { print("Graph contains a cycle!") } diff --git a/Tests/PNDependencyGraphTests/PNDependencyGraphTests.swift b/Tests/PNDependencyGraphTests/PNDependencyGraphTests.swift index 381479d..8bd9d46 100644 --- a/Tests/PNDependencyGraphTests/PNDependencyGraphTests.swift +++ b/Tests/PNDependencyGraphTests/PNDependencyGraphTests.swift @@ -3,12 +3,12 @@ import Testing @Test("Many dependencies") func manyDeps() async throws { - let graph = DependencyGraph() - let a = graph.addNode("A") - let b = graph.addNode("B") - let c = graph.addNode("C") - let d = graph.addNode("D") - let e = graph.addNode("E") + let graph = PNGraph() + let a = graph.add(identifier: "A") + let b = graph.add(identifier: "B") + let c = graph.add(identifier: "C") + let d = graph.add(identifier: "D") + let e = graph.add(identifier: "E") b.addDependency(node: a) c.addDependency(node: b) @@ -22,7 +22,7 @@ func manyDeps() async throws { @Test("Empty graph") func emptyGraph() async throws { - let graph = DependencyGraph() + let graph = PNGraph() let compiled = try graph.compile() @@ -31,8 +31,8 @@ func emptyGraph() async throws { @Test("Single node graph") func singleNode() async throws { - let graph = DependencyGraph() - let a = graph.addNode("A") + let graph = PNGraph() + let a = graph.add(identifier: "A") let compiled = try graph.compile() @@ -41,16 +41,16 @@ func singleNode() async throws { @Test("Cycle") func cycle() async throws { - let graph = DependencyGraph() - let a = graph.addNode("A") - let b = graph.addNode("B") - let c = graph.addNode("C") + let graph = PNGraph() + let a = graph.add(identifier: "A") + let b = graph.add(identifier: "B") + let c = graph.add(identifier: "C") a.addDependency(node: c) c.addDependency(node: b) b.addDependency(node: a) - #expect(throws: CompilationError.self) { + #expect(throws: PNCompilationError.self) { _ = try graph.compile() } }