Code Monkey home page Code Monkey logo

sitrep's Introduction

Sitrep logo

Twitter: @twostraws

Sitrep is a source code analyzer for Swift projects, giving you a high-level overview of your code:

  • A count of your classes, structs, enums, protocols, and extensions.
  • Total lines of code, and also source lines of code (minus comments and whitespace).
  • Which file and type are the longest, plus their source lines of code.
  • Which imports you’re using and how often.
  • How many UIViews, UIViewControllers, and SwiftUI views are in your project.

Behind the scenes, Sitrep captures a lot more information that could be utilized – how many functions you have, how many comments (regular and documentation), how large your enums are, and more. These aren’t currently reported, but could be in a future release. It’s also written as both a library and an executable, so it can be integrated elsewhere as needed.

Sitrep is built using Apple’s SwiftSyntax, which means it parses Swift code accurately and efficiently.

Note: Please make sure that the SwiftSyntax version specified in Package.swift matches your current Swift tools version.

Installation

If you want to install the Sitrep command line tool, you have three options: Homebrew, Mint, or building it from the command line yourself.

Use this command for Homebrew:

brew install twostraws/brew/sitrep

Using Homebrew allows you to run sitrep directly from the command line.

For Mint, install and run Sitrep with these command:

mint install twostraws/Sitrep@main
mint run sitrep@main

And finally, to build and install the command line tool yourself, clone the repository and run make install:

git clone https://github.com/twostraws/Sitrep
cd Sitrep
make install

As with the Homebrew option, building the command line tool yourself allows you to use the sitrep command directly from the command line.

Using Sitrep as a library

Sitrep is implemented as a library that does all the hard work of scanning and reporting, plus a small front end that handles reading and writing on the command line. As an alternative to using Sitrep from the command line, you can also use its library SitrepCore from inside your own Swift code.

First, add Sitrep as a dependency in your Package.swift file:

let package = Package(
    //...
    dependencies: [
        .package(url: "https://github.com/twostraws/Sitrep", .branch("master"))
    ],
    //...
)

Then import SitrepCore wherever you’d like to use it.

Command line flags

When run on the command line without any flags, Sitrep will automatically scan your current directory and print its findings as text. To control this behavior, Sitrep supports several command line flags:

  • -c lets you specify a path to your .sitrep.yml configuration file, if you have one.
  • -f sets the output format. For example, -f json enables JSON output. The default behavior is text output, which is equivalent to -f text.
  • -i will print debug information, showing the settings Sitrep would use if a real scan were requested, then exits.
  • -p sets the path Sitrep should scan. This defaults to your current working directory.
  • -h prints command line help.

Configuration

You can customize the behavior of Sitrep by creating a .sitrep.yml file in the directory you wish to scan. This is a YAML file that allows you to provide permanent options for scanning this path, although right now this is limited to one thing: an array of directory names to exclude from the scan.

For example, if you wanted to exclude the .build directory and your tests, you might create a .sitrep.yml file such as this one:

excluded:
  - .build
  - Tests

You can ask Sitrep to use a custom configuration file using the -c parameter, for example sitrep -c /path/to/.sitrep.yml -p /path/to/swift/project.

Alternatively, you can use the -i parameter to have Sitrep tell you the configuration options it would use in a real analysis run. This will print the configuration information then exit.

Try it yourself

Sitrep is written using Swift 5.8. You can either build and run the executable directly, or integrate the SitrepCore library into your own code.

To build Sitrep, clone this repository and open Terminal in the repository root directory. Then run:

swift build
swift run sitrep -p ~/path/to/your/project/root

If you would like to keep a copy of the sitrep executable around, find it in the .debug directory after running swift build.

To run Sitrep from the command line just provide it with the name of a project directory to parse – it will locate all Swift files recursively from there. Alternatively, just using sitrep by itself will scan the current directory.

Contribution guide

Any help you can offer with this project is most welcome, and trust me: there are opportunities big and small, so that someone with only a small amount of Swift experience can help.

Some suggestions you might want to explore:

  • Converting more of the tracked data (number of functions, parameters to functions, length of functions, etc) into reported data.
  • Reading more data from the parsed files, and using it to calculate things such as cyclomatic complexity.
  • Reading non-Swift data, such as number of storyboard scenes, number of outlets, number of assets in asset catalogs, etc.

Please ensure you write tests to accompany any code you contribute, and that SwiftLint returns no errors or warnings.

Credits

Sitrep was designed and built by Paul Hudson, and is copyright © Paul Hudson 2023. Sitrep is licensed under the Apache License v2.0 with Runtime Library Exception; for the full license please see the LICENSE file.

Sitrep is built on top of Apple’s SwiftSyntax library for parsing code, which is also available under the Apache License v2.0 with Runtime Library Exception.

Swift, the Swift logo, and Xcode are trademarks of Apple Inc., registered in the U.S. and other countries.

If you find Sitrep useful, you might find my website full of Swift tutorials equally useful: Hacking with Swift.

sitrep's People

Contributors

alexito4 avatar beatrupp avatar daveverwer avatar kikeenrique avatar lutzifer avatar melbic avatar rigovides avatar sherlouk avatar tib avatar twostraws avatar valihar avatar vandrj avatar yhkaplan avatar yume190 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

sitrep's Issues

Fails to build with Xcode 13

When I attempted to install via brew on Big Sur 11.6 with Xcode 13.0 installed sitrep fails to build:

~  brew install twostraws/brew/sitrep
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 1 tap (homebrew/core).
==> Updated Formulae
Updated 1 formula.

==> Downloading https://github.com/twostraws/Sitrep/archive/2.0.0.zip
Already downloaded: /Users/oliver/Library/Caches/Homebrew/downloads/d4eb3eace3c707e956021a5f09274a6488a1a45867c75fa7ab40206312e8a965--Sitrep-2.0.0.zip
==> Installing sitrep from twostraws/brew
Warning: Building now – this might take a few minutes.
==> swift build --configuration release --disable-sandbox
Last 15 lines from /Users/oliver/Library/Logs/Homebrew/sitrep/01.swift:
      let startOffset = Int(cnode.range.offset)
                            ~~~~~ ^~~~~
/private/tmp/sitrep-20210922-63336-1tl3wq4/Sitrep-2.0.0/.build/checkouts/swift-syntax/Sources/SwiftSyntax/RawSyntax.swift:157:55: error: value of type 'CSyntaxNode' (aka 'swiftparse_syntax_node_t') has no member 'range'
      let end = utf8.index(begin, offsetBy: Int(cnode.range.length))
                                                ~~~~~ ^~~~~
/private/tmp/sitrep-20210922-63336-1tl3wq4/Sitrep-2.0.0/.build/checkouts/swift-syntax/Sources/SwiftSyntax/RawSyntax.swift:873:32: error: value of type 'CSyntaxNode' (aka 'swiftparse_syntax_node_t') has no member 'range'
    let byteLength = Int(cnode.range.length)
                         ~~~~~ ^~~~~
/private/tmp/sitrep-20210922-63336-1tl3wq4/Sitrep-2.0.0/.build/checkouts/swift-syntax/Sources/SwiftSyntax/SyntaxParser.swift:195:57: error: missing argument for parameter #3 in call
    let c_top = swiftparse_parse_string(c_parser, source)
                                                        ^
                                                        , <#Int#>
_InternalSwiftSyntaxParser.swiftparse_parse_string:1:13: note: 'swiftparse_parse_string' declared here
public func swiftparse_parse_string(_: swiftparse_parser_t!, _ source: UnsafePointer<CChar>!, _ len: Int) -> swiftparse_client_node_t!
            ^

Not working for Xcode 15.3

I have Xcode 15.3 installed and got this error while trying to install Sitrep:

brew install twostraws/brew/sitrep
==> Tapping twostraws/brew
Cloning into '/opt/homebrew/Library/Taps/twostraws/homebrew-brew'...
remote: Enumerating objects: 18, done.
remote: Counting objects: 100% (18/18), done.
remote: Compressing objects: 100% (17/17), done.
remote: Total 18 (delta 4), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (18/18), 4.12 KiB | 2.06 MiB/s, done.
Resolving deltas: 100% (4/4), done.
Tapped 2 formulae (13 files, 10.0KB).
==> Fetching twostraws/brew/sitrep
==> Downloading https://github.com/twostraws/Sitrep/archive/3.0.0.zip
==> Downloading from https://codeload.github.com/twostraws/Sitrep/zip/refs/tags/3.0.0
##O#-  #
==> Installing sitrep from twostraws/brew
Error: Your Command Line Tools are too outdated.
Update them from Software Update in System Settings.

If that doesn't show you any updates, run:
  sudo rm -rf /Library/Developer/CommandLineTools
  sudo xcode-select --install

Alternatively, manually download them from:
  https://developer.apple.com/download/all/.
You should download the Command Line Tools for Xcode 15.1.

Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib

MacBook Pro M1, 32GB RAM, 16-inch, 2021
OS: 13.2.1 (22D68)
xCode: 14.2 (14C18)
Installed via Homebrew
I am getting following error in terminal.

dyld[66107]: Library not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylib
  Referenced from: <5060E796-F2F6-3624-8F9E-12E768636538> /opt/homebrew/Cellar/sitrep/2.1.0/bin/sitrep
  Reason: tried: '/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file, not in dyld cache), '/System/Volumes/Preboot/Cryptexes/OS/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/opt/homebrew/Cellar/sitrep/2.1.0/bin/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file, not in dyld cache), '/System/Volumes/Preboot/Cryptexes/OS/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/opt/homebrew/Cellar/sitrep/2.1.0/bin/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS@rpath/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file, not in dyld cache), '/System/Volumes/Preboot/Cryptexes/OS/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/opt/homebrew/Cellar/sitrep/2.1.0/bin/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file, not in dyld cache), '/System/Volumes/Preboot/Cryptexes/OS/usr/lib/swift/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/opt/homebrew/Cellar/sitrep/2.1.0/bin/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/System/Volumes/Preboot/Cryptexes/OS/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/swift-5.5/macosx/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/usr/local/lib/lib_InternalSwiftSyntaxParser.dylib' (no such file), '/usr/lib/lib_InternalSwiftSyntaxParser.dylib' (no such file, not in dyld cache)
zsh: abort      sitrep

Publicise SitrepCore

Hey @twostraws 👋

An awesome little tool that you've created here! I wonder if you'd be interesting in enabling SitrepCore as a product?

It would allow other people's tools to build on top of the great stuff you've built as part of their own projects. Of course, you have the JSON output which could be used with ShellOut and some Codable stuff but this a lot more to manage (and introduces more routes for problems) versus using the library directly.

In theory it would just be a case of adding the product to the Package.swift and making a couple extra things public!

Homebrew Installation Doesn't Work

After installing via homebrew, then in a project directory that contains the .xcodeproj file running sitrep this gives 0 files scanned.
Do I need to create the .yml file? Or do anything else?

Fails to work with Version 13.3 (13E113)

~/Library/org.swift.swiftpm/collections.json has been deprecated. Please delete it and use the new ~/Library/org.swift.swiftpm/configuration/collections.json instead.
error: Could not find Package.swift in this directory or any of its parent directories.

Followed the steps to setup and install and got the error above.

Fingers crossed that changing the json fixes my issues. Just posting so folks are aware of changes in Xcode.

Inheriting typealiases doesn't work

Typealiasing a class (e.g. typealias UIVC = UIViewController) and inheriting from this typealias (e.g. class SomeClass: UIVC { ... }) doesn't count inheritance from the original class (UIViewController in this case).

Extensions ignored in type length analysis

How to reproduce:

  1. Create empty directory named "Foobar"

  2. Initialize swift package via $ swift package init

  3. Change …

    struct Foobar {
        var text = "Hello, World!"
    }

    … to …

struct Foobar {
    var text = "Hello, World!"
// }

// extension Foobar {
    func foo() -> Int {
        var i: Int = 0
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        i += 1
        return i
    }
}
  1. run $ sitrep
Overview
   Files scanned: 5
   Structs: 1
   Classes: 1
   Enums: 0
   Protocols: 0
   Extensions: 0

Sizes
   Total lines of code: 105
   Source lines of code: 93
   Longest file: Foobar.swift (45 source lines)
   Longest type: Foobar (45 source lines)

Structure
   Imports: XCTest (3), FoobarTests (1), Foobar (1), PackageDescription (1)
   UIKit View Controllers: 0
   UIKit Views: 0
   SwiftUI Views: 0
  1. Uncomment these lines …
// }

// extension Foobar {
  1. run $ sitrep again
Overview
   Files scanned: 5
   Structs: 1
   Classes: 1
   Enums: 0
   Protocols: 0
---   Extensions: 0
+++   Extensions: 1

Sizes
   Total lines of code: 105
   Source lines of code: 93
   Longest file: Foobar.swift (45 source lines)
---   Longest type: Foobar (45 source lines)
+++   Longest type: FoobarTests (11 source lines)

Structure
   Imports: XCTest (3), FoobarTests (1), Foobar (1), PackageDescription (1)
   UIKit View Controllers: 0
   UIKit Views: 0
   SwiftUI Views: 0
  1. Notice how Foobar is now suddenly not considered the longest type any more.

This is wrong.
The contents of a type's extensions should be considered content of the type.

Debug Logs

It'd be nice if this tool could be run at different verbosity levels

Sitrep vs. cloc Results

Scanning my current branch of Alamofire, Sitrep gives these LOC results:

Sizes
   Total lines of code: 11102
   Source lines of code: 9481

However, cloc gives these results:

Language                     files          blank        comment           code
-------------------------------------------------------------------------------
Swift                           32           1606           3598           5897

Perhaps Sitrep could use a similar break down?

Add ability via configuration file to additionally scan swift packages

Hey Paul,

As the good Swift developers we are, we strive to encapsulate reusable code into Swift Packages. Do you think that it would be easy to enhance SitRep to go inspecting Swift Package dependencies too and combine the results into a single report, maybe broken down by app / packages? My use case would be to only count lines of code that I've personally written.

I'm sure this could be done by just invoking SitRep on all of the local swift packages but that would require some addition and combining results from several runs.

Thoughts on the following?

  • Configuration to specify which Swift Package references to be interested in
  • Configuration to specify where Swift Package Manager is configured to save local copies
  • Configuration to specify path to LOCAL Swift Packages --> This is usually my workflow, develop locally, push, then have app checkout from GitHub

Add ability to create a report per-target/extension

Hey Paul,

Similar to #39, I'm curious on your take of how easy it would be to modify SitRep to allow the caller to specify a flag to output a report per target, per extension, etc.

For example, 'I have an app with an app, app clip, widget extension, live activity widget extension' and so on. The idea here would be to see at a glance where the majority of the code is from a target level. Potentially some interesting analysis to 'refactor shared code into swift package'.

Can't install

Hello!

make install

swift build -c release
Fetching https://github.com/apple/swift-syntax.git
Completed resolution in 11.75s
Cloning https://github.com/apple/swift-syntax.git
Resolving https://github.com/apple/swift-syntax.git at 0.50100.0
/Users/alur/Sitrep/.build/checkouts/swift-syntax/Sources/SwiftSyntax/AtomicCounter.swift:13:2: error: unknown attribute '_implementationOnly'
@_implementationOnly import _CSwiftSyntax
 ^
/Users/alur/Sitrep/.build/checkouts/swift-syntax/Sources/SwiftSyntax/SyntaxParser.swift:17:8: error: no such module '_InternalSwiftSyntaxParser'
import _InternalSwiftSyntaxParser
       ^

make: *** [install] Error 1

Fatal Error

After install it by Homebrew.
I got this error fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip: no files specified when try to use it.
When i run sitrep.

Issues with swift-tools-version:5.2

I'm getting the following error when attempting to add Sitrep to my Package.swift:

product 'Sitrep' not found. It is required by target 'App'.

This is my Package.swift:

// swift-tools-version:5.2
import PackageDescription

let package = Package(
    name: "PSVaporV4",
    platforms: [
       .macOS(.v10_15)
    ],
    dependencies: [
        // 💧 A server-side Swift web framework.
        .package(url: "https://github.com/vapor/vapor.git", from: "4.0.0-rc"),
...
        .package(url: "https://github.com/twostraws/Sitrep", .branch("master"))
    ],
    targets: [
    .target(name: "App", dependencies: [
...
        .product(name: "Sitrep", package: "Sitrep")
    ]),
    ],
       swiftLanguageVersions: [.v5]
)

I've had some other issues migrating to packages using swift-tools-version:5.2. Is there something I'm doing wrong here or do I need to make a change to accommodate this swift-tools-version?

Edit: I know the package says it supports Swift 5.1, so if this just isn't supported in 5.2 that's totally fine.

Thanks!

The Build was completed with Zero results.

Hello,

I tried to execute the Sitrep command under the Cocoapods Classes directory. But I got an empty result.

swift run Sitrep -p ~/Users/duruldalkanat/ios_snapshot_testing/Source/VHFeature-iOS/VHFeature-iOS/Classes

Distro: OS X 12.6
Xcode 13.4.1
Build version 13F100

Build complete! (0.20s)
SITREP

Overview
Files scanned: 0
Structs: 0
Classes: 0
Enums: 0
Protocols: 0
Extensions: 0

Sizes
Total lines of code: 1
Source lines of code: 1

Structure
Imports:
UIKit View Controllers: 0
UIKit Views: 0
SwiftUI Views: 0

Mint install fails

Installing via Mint now fails since it's expecting to clone "master" but now there is no such branch but "main" instead.

You can install if you specify the branch e.g:

mint install twostraws/Sitrep@main

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.