attractor-swift 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +6 -0
- data/LICENSE +21 -0
- data/README.md +84 -0
- data/Rakefile +8 -0
- data/attractor-swift.gemspec +40 -0
- data/bin/console +7 -0
- data/bin/setup +5 -0
- data/lib/attractor/calculators/swift_calculator.rb +12 -0
- data/lib/attractor/detectors/swift_detector.rb +14 -0
- data/lib/attractor/swift/version.rb +5 -0
- data/lib/attractor/swift.rb +16 -0
- metadata +129 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 783075f65d0b5fc72db27fbe146c75e4f08197743f0ac13d96f2c6cc11a53c44
|
|
4
|
+
data.tar.gz: d79761047aab01a58eff2bb89aab868b589affeb8abe9ad0dfbf01e0ca943b71
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f95d230978f00d012ff0d71545c3cfddfc1934a79ebe4bc334a56cb5a89840823ea815741b2134c029c6ace693d419a2d632776831455e7eec34a9fb0bd9af3f
|
|
7
|
+
data.tar.gz: 98064df8b81e17c7ffd1778cc781d83ea1257d7cabfa58945e247d3eb6416c0fed556d25ca4c7dcf187d0d86d08862951bc5e63fe5c3041a0fc62025b2b33ef0
|
data/.gitignore
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Julian Rubisch
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# attractor-swift
|
|
2
|
+
|
|
3
|
+
Swift plugin for [attractor](https://github.com/julianrubisch/attractor), the churn vs. complexity
|
|
4
|
+
tool. Complexity is the per-function cyclomatic complexity reported by
|
|
5
|
+
[lizard](https://github.com/terryyin/lizard); churn comes from attractor's git history.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
gem install attractor attractor-swift
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
lizard is a Python tool. attractor runs it through [uv](https://docs.astral.sh/uv/) when
|
|
14
|
+
`lizard` itself is not on your PATH:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
# one of
|
|
18
|
+
brew install uv # then `uvx lizard` fetches lizard on first use
|
|
19
|
+
pip install lizard
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
attractor finds the plugin by its gem name; nothing to configure.
|
|
23
|
+
|
|
24
|
+
## Usage
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
cd my-swift-project
|
|
28
|
+
attractor calc -c 0 --format table # every file, table
|
|
29
|
+
attractor calc --format json # per-function details with line ranges
|
|
30
|
+
attractor diff --base main --head HEAD -c 0 # complexity delta of a branch
|
|
31
|
+
attractor report # the interactive chart
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Method-level `details` carry lizard's CCN and location:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
"details": {
|
|
38
|
+
"total": {"score": 3, "line": 6, "end_line": 15},
|
|
39
|
+
"pay": {"score": 3, "line": 24, "end_line": 30}
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Two things to know about the numbers:
|
|
44
|
+
|
|
45
|
+
- CCN is McCabe cyclomatic complexity, a different scale from flog's Ruby score. attractor
|
|
46
|
+
reports per language, so they are never compared.
|
|
47
|
+
- lizard names functions without their type (`total`, not `Cart.total`). Two functions with
|
|
48
|
+
the same name in one file are kept apart by their start line (`card@32`, `card@50`).
|
|
49
|
+
|
|
50
|
+
Force a specific runner with `ATTRACTOR_LIZARD="python -m lizard"`.
|
|
51
|
+
|
|
52
|
+
## Using this repository as a template for another language
|
|
53
|
+
|
|
54
|
+
Everything language-specific is two strings and a detector. To make `attractor-kotlin`:
|
|
55
|
+
|
|
56
|
+
1. Copy this repository. Rename `swift` → `kotlin` in file names, module names, the gemspec and
|
|
57
|
+
the workflow.
|
|
58
|
+
2. `lib/attractor/calculators/kotlin_calculator.rb`: `language: "kotlin"` (a name from
|
|
59
|
+
`lizard --help`, under `-l`), `file_extension: "kt"` (a regex-ish string is fine:
|
|
60
|
+
`"(kt|kts)"`), `@type = "Kotlin"`.
|
|
61
|
+
3. `lib/attractor/detectors/kotlin_detector.rb`: what marks a project (`build.gradle.kts`,
|
|
62
|
+
any `*.kt`).
|
|
63
|
+
4. Replace the fixture in `spec/fixtures/` and the expected numbers in the calculator spec;
|
|
64
|
+
run `uvx lizard -l kotlin --csv spec/fixtures/...` once to get them.
|
|
65
|
+
5. Push, tag, `rake release`.
|
|
66
|
+
|
|
67
|
+
Languages lizard scores today include C/C++, C#, Go, Java, JavaScript, Kotlin, Lua, Objective-C,
|
|
68
|
+
PHP, Python, Rust, Scala, Swift, TypeScript and more. For languages with a better native
|
|
69
|
+
metric tool (Ruby has flog, JavaScript has escomplex with class and import context), write
|
|
70
|
+
the calculator against that tool instead, as attractor-ruby and attractor-javascript do.
|
|
71
|
+
|
|
72
|
+
## Development
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
bin/setup
|
|
76
|
+
bundle exec rspec # the lizard integration example skips without lizard or uv
|
|
77
|
+
bundle exec standardrb
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Against an unreleased attractor: `ATTRACTOR_PATH=../attractor bundle install`.
|
|
81
|
+
|
|
82
|
+
## License
|
|
83
|
+
|
|
84
|
+
MIT.
|
data/Rakefile
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
|
4
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
5
|
+
require "attractor/swift/version"
|
|
6
|
+
|
|
7
|
+
Gem::Specification.new do |spec|
|
|
8
|
+
spec.name = "attractor-swift"
|
|
9
|
+
spec.version = Attractor::Swift::VERSION
|
|
10
|
+
spec.authors = ["Julian Rubisch"]
|
|
11
|
+
spec.email = ["julian@julianrubisch.at"]
|
|
12
|
+
|
|
13
|
+
spec.summary = "Attractor plugin for Swift: churn vs. cyclomatic complexity via lizard"
|
|
14
|
+
spec.description = <<-DESCRIPTION
|
|
15
|
+
Attractor plugin for the Swift programming language. Scores files with lizard's
|
|
16
|
+
per-function cyclomatic complexity and attractor's git churn.
|
|
17
|
+
DESCRIPTION
|
|
18
|
+
spec.homepage = "https://github.com/julianrubisch/attractor-swift"
|
|
19
|
+
spec.licenses = ["MIT"]
|
|
20
|
+
spec.required_ruby_version = ">= 3.3"
|
|
21
|
+
|
|
22
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
|
23
|
+
spec.metadata["source_code_uri"] = spec.homepage
|
|
24
|
+
spec.metadata["bug_tracker_uri"] = "#{spec.homepage}/issues"
|
|
25
|
+
spec.metadata["changelog_uri"] = "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
26
|
+
|
|
27
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
28
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
|
29
|
+
f.match(%r{^(spec|\.github)/}) || %w[.rspec .rspec_status .standard.yml .tool-versions].include?(f)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
spec.require_paths = ["lib"]
|
|
33
|
+
|
|
34
|
+
spec.add_dependency "attractor", ">= 2.8"
|
|
35
|
+
|
|
36
|
+
spec.add_development_dependency "bundler", ">= 2.7"
|
|
37
|
+
spec.add_development_dependency "rake", "~> 13.0"
|
|
38
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
|
39
|
+
spec.add_development_dependency "standard"
|
|
40
|
+
end
|
data/bin/console
ADDED
data/bin/setup
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Attractor
|
|
4
|
+
# Everything language-specific is these two strings; the scoring lives in
|
|
5
|
+
# Attractor::LizardCalculator (attractor >= 2.8).
|
|
6
|
+
class SwiftCalculator < LizardCalculator
|
|
7
|
+
def initialize(**options)
|
|
8
|
+
super(language: "swift", file_extension: "swift", **options)
|
|
9
|
+
@type = "Swift"
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Attractor
|
|
4
|
+
class SwiftDetector < BaseDetector
|
|
5
|
+
# A package manifest or an Xcode project is the cheap signal; a bare directory of .swift
|
|
6
|
+
# files (a script, a playground export) still counts, hence the glob fallback.
|
|
7
|
+
def detect
|
|
8
|
+
root = Dir.pwd
|
|
9
|
+
File.exist?(File.join(root, "Package.swift")) ||
|
|
10
|
+
Dir.glob(File.join(root, "*.{xcodeproj,xcworkspace}")).any? ||
|
|
11
|
+
Dir.glob(File.join(root, "**", "*.swift")).any?
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
require "attractor/swift/version"
|
|
2
|
+
|
|
3
|
+
require "attractor"
|
|
4
|
+
require "attractor/registry_entry"
|
|
5
|
+
require "attractor/calculators/lizard_calculator"
|
|
6
|
+
require "attractor/calculators/swift_calculator"
|
|
7
|
+
require "attractor/detectors/base_detector"
|
|
8
|
+
require "attractor/detectors/swift_detector"
|
|
9
|
+
|
|
10
|
+
module Attractor
|
|
11
|
+
module Swift
|
|
12
|
+
class Error < StandardError; end
|
|
13
|
+
|
|
14
|
+
Attractor.register(Attractor::RegistryEntry.new(type: "swift", detector_class: SwiftDetector, calculator_class: SwiftCalculator))
|
|
15
|
+
end
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: attractor-swift
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Julian Rubisch
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 2026-09-22 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: attractor
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.8'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.8'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: bundler
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '2.7'
|
|
33
|
+
type: :development
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '2.7'
|
|
40
|
+
- !ruby/object:Gem::Dependency
|
|
41
|
+
name: rake
|
|
42
|
+
requirement: !ruby/object:Gem::Requirement
|
|
43
|
+
requirements:
|
|
44
|
+
- - "~>"
|
|
45
|
+
- !ruby/object:Gem::Version
|
|
46
|
+
version: '13.0'
|
|
47
|
+
type: :development
|
|
48
|
+
prerelease: false
|
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
50
|
+
requirements:
|
|
51
|
+
- - "~>"
|
|
52
|
+
- !ruby/object:Gem::Version
|
|
53
|
+
version: '13.0'
|
|
54
|
+
- !ruby/object:Gem::Dependency
|
|
55
|
+
name: rspec
|
|
56
|
+
requirement: !ruby/object:Gem::Requirement
|
|
57
|
+
requirements:
|
|
58
|
+
- - "~>"
|
|
59
|
+
- !ruby/object:Gem::Version
|
|
60
|
+
version: '3.0'
|
|
61
|
+
type: :development
|
|
62
|
+
prerelease: false
|
|
63
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
64
|
+
requirements:
|
|
65
|
+
- - "~>"
|
|
66
|
+
- !ruby/object:Gem::Version
|
|
67
|
+
version: '3.0'
|
|
68
|
+
- !ruby/object:Gem::Dependency
|
|
69
|
+
name: standard
|
|
70
|
+
requirement: !ruby/object:Gem::Requirement
|
|
71
|
+
requirements:
|
|
72
|
+
- - ">="
|
|
73
|
+
- !ruby/object:Gem::Version
|
|
74
|
+
version: '0'
|
|
75
|
+
type: :development
|
|
76
|
+
prerelease: false
|
|
77
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
description: |2
|
|
83
|
+
Attractor plugin for the Swift programming language. Scores files with lizard's
|
|
84
|
+
per-function cyclomatic complexity and attractor's git churn.
|
|
85
|
+
email:
|
|
86
|
+
- julian@julianrubisch.at
|
|
87
|
+
executables: []
|
|
88
|
+
extensions: []
|
|
89
|
+
extra_rdoc_files: []
|
|
90
|
+
files:
|
|
91
|
+
- ".gitignore"
|
|
92
|
+
- CHANGELOG.md
|
|
93
|
+
- Gemfile
|
|
94
|
+
- LICENSE
|
|
95
|
+
- README.md
|
|
96
|
+
- Rakefile
|
|
97
|
+
- attractor-swift.gemspec
|
|
98
|
+
- bin/console
|
|
99
|
+
- bin/setup
|
|
100
|
+
- lib/attractor/calculators/swift_calculator.rb
|
|
101
|
+
- lib/attractor/detectors/swift_detector.rb
|
|
102
|
+
- lib/attractor/swift.rb
|
|
103
|
+
- lib/attractor/swift/version.rb
|
|
104
|
+
homepage: https://github.com/julianrubisch/attractor-swift
|
|
105
|
+
licenses:
|
|
106
|
+
- MIT
|
|
107
|
+
metadata:
|
|
108
|
+
homepage_uri: https://github.com/julianrubisch/attractor-swift
|
|
109
|
+
source_code_uri: https://github.com/julianrubisch/attractor-swift
|
|
110
|
+
bug_tracker_uri: https://github.com/julianrubisch/attractor-swift/issues
|
|
111
|
+
changelog_uri: https://github.com/julianrubisch/attractor-swift/blob/main/CHANGELOG.md
|
|
112
|
+
rdoc_options: []
|
|
113
|
+
require_paths:
|
|
114
|
+
- lib
|
|
115
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
|
+
requirements:
|
|
117
|
+
- - ">="
|
|
118
|
+
- !ruby/object:Gem::Version
|
|
119
|
+
version: '3.3'
|
|
120
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - ">="
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '0'
|
|
125
|
+
requirements: []
|
|
126
|
+
rubygems_version: 3.6.2
|
|
127
|
+
specification_version: 4
|
|
128
|
+
summary: 'Attractor plugin for Swift: churn vs. cyclomatic complexity via lizard'
|
|
129
|
+
test_files: []
|