A linter tool for Interface Builder

Overview

IBLinter

Build Status Swift 5.0

A linter tool to normalize .xib and .storyboard files. Inspired by realm/SwiftLint

Installation

Using Homebrew

$ brew install iblinter

Using Mint

$ mint install IBDecodable/IBLinter

Using CocoaPods

pod 'IBLinter'

This will download the IBLinter binaries and dependencies in Pods/ during your next pod install execution and will allow you to invoke it via ${PODS_ROOT}/IBLinter/bin/iblinter in your Script Build Phases.

Compiling from source

You can build from source by cloning this repository and running

$ make install

iblinter will be installed in /usr/local/bin.

Usage

You can see all description by iblinter help

$ iblinter help
Available commands:

   help      Display general or command-specific help
   lint      Print lint warnings and errors (default command)
   version   Display the current version of iblinter

Xcode

Add a Run Script Phase to integrate IBLinter with Xcode

if which iblinter >/dev/null; then
  iblinter lint
else
  echo "warning: IBLinter not installed, download from https://github.com/IBDecodable/IBLinter"
fi

Alternatively, if you've installed IBLinter via CocoaPods the script should look like this:

"${PODS_ROOT}/IBLinter/bin/iblinter"

Requirements

IBLinter requires Swift5.0 runtime. Please satisfy at least one of following requirements.

Rules

All rules are documented in Rules.md

Pull requests are encouraged.

Configuration

You can configure IBLinter by adding a .iblinter.yml file from project root directory.

key description
enabled_rules Enabled rules id.
disabled_rules Disabled rules id.
excluded Path to ignore for lint.
included Path to include for lint.
custom_module_rule Custom module rule configs.
use_base_class_rule Use base class rule configs.
view_as_device_rule View as device rule configs.

CustomModuleConfig

You can configure custom_module rule by CustomModuleConfig list.

key description
module Module name.
included Path to *.swift classes of the module for custom_module lint.
excluded Path to ignore for *.swift classes of the module for custom_module lint.

UseBaseClassConfig

You can configure use_base_class rule by UseBaseClassConfig list.

key description
element_class Element class name.
base_classes Base classes of the element class.

Note: UseBaseClassRule does not work for classes that inherit base class. You need to add all classes to base_classes to check.

ViewAsDeviceConfig

You can configure view_as_device rule by ViewAsDeviceConfig. If there are no config, device_id is set as retina4_7.

key description
device_id Device id for device.

appx. Table of mapping device name to device_id (on Xcode 10.2)

device name device id
iPhone 4s retina3_5
iPhone SE retina4_0
iPhone 8 retina4_7
iPhone 8 Plus retina5_5
iPhone XS retina5_9
iPhone XR retina6_1
iPhone XS Max retina6_5

UseTraitCollectionsConfig

You can configure use_trait_collections rule by UseTraitCollectionsConfig`. If there is no config then use_trait_collections is set to true

key description
enabled true
enabled_rules:
  - relative_to_margin
  - use_trait_collections
disabled_rules:
  - custom_class_name
excluded:
  - Carthage
  - App
included:
  - App/Views
custom_module_rule:
  - module: UIComponents
    included:
      - UIComponents/Classes
    excluded:
      - UIComponents/Classes/Config/Generated
use_base_class_rule:
  - element_class: UILabel
    base_classes:
      - PrimaryLabel
      - SecondaryLabel
view_as_device_rule:
  device_id: retina4_0
use_trait_collections_rule:
  enabled: false
Comments
  • Incorrect warning: duplicate element id

    Incorrect warning: duplicate element id

    IBlinter says SignIn.storyboard:0:0: warning: duplicate element id 9SU-qi-UFm. But in fact, there is only one element whose id is 9SU-qi-UFm . Is this the expected behavior?

    Version: 0.4.26 Using: Homebrew and CocoaPods - same result for both .iblinter.yml:

    enabled_rules:
      - misplaced
      - view_as_device
      - image_resources
    excluded:
      - Pods
    view_as_device_rule:
      device_id: retina5_9
    

    Search Results for9SU-qi-UFm :

    • <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" usesAttributedText="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9SU-qi-UFm">
    • <constraint firstItem="9SU-qi-UFm" firstAttribute="leading" secondItem="L3f-4j-PFL" secondAttribute="leading" id="TtQ-0E-1RQ"/>
    • <constraint firstItem="9SU-qi-UFm" firstAttribute="centerX" secondItem="L3f-4j-PFL" secondAttribute="centerX" id="Y9A-8a-Q6E"/>
    • <constraint firstItem="9SU-qi-UFm" firstAttribute="centerY" secondItem="L3f-4j-PFL" secondAttribute="centerY" id="cnK-2q-oAm"/>
    • <constraint firstAttribute="trailing" secondItem="9SU-qi-UFm" secondAttribute="trailing" id="gxV-NN-gNj"/>
    • <outlet property="descriptionsTextView" destination="9SU-qi-UFm" id="ar7-62-iKJ"/>

    I have tried DuplicateIDRuleTests with the latest version of the source code, but it seems to be failing.

    Test Suite 'DuplicateIDRuleTests' started at 2021-05-11 16:55:32.057
    Test Case '-[IBLinterKitTest.DuplicateIDRuleTests testDuplicateId]' started.
    /Users/wata/tmp/IBLinter/Tests/IBLinterKitTest/Rules/DuplicateIDRuleTests.swift:20: error: -[IBLinterKitTest.DuplicateIDRuleTests testDuplicateId] : XCTAssertEqual failed: ("5") is not equal to ("2")
    /Users/wata/tmp/IBLinter/Tests/IBLinterKitTest/Rules/DuplicateIDRuleTests.swift:22: error: -[IBLinterKitTest.DuplicateIDRuleTests testDuplicateId] : XCTAssertEqual failed: ("["duplicate element id fullscreen", "duplicate element id iN0-l3-epB", "duplicate element id aEU-56-OK8", "duplicate element id fullscreen", "duplicate element id fullscreen"]") is not equal to ("["duplicate element id iN0-l3-epB", "duplicate element id aEU-56-OK8"]")
    Test Case '-[IBLinterKitTest.DuplicateIDRuleTests testDuplicateId]' failed (0.772 seconds).
    Test Suite 'DuplicateIDRuleTests' failed at 2021-05-11 16:55:32.829.
    	 Executed 1 test, with 2 failures (0 unexpected) in 0.772 (0.772) seconds
    
    opened by wata 12
  • IBLinter 0.4.14 is broken

    IBLinter 0.4.14 is broken

    after installing via cocoa pods:

    xcode 10.2 / swift 5

    dyld: Library not loaded: @rpath/libswiftCore.dylib
      Referenced from: XcodeProject/./Pods/IBLinter/bin/iblinter
      Reason: image not found
    Abort trap: 6
    

    reverted to 0.4.13 and it works

    opened by nysander 9
  • There is warning when installed by pods

    There is warning when installed by pods

    There is warning when installed by pods: warning: no rule to process file '/Users/.../XcodeProjects/ScriptsTest/Pods/IBLinter/bin/iblinter' of type compiled.mach-o.executable for architecture x86_64

    Also I see that IBLinter hierarchy is not as swiftlint or swiftgen. Maybe that's why there is that warning. image

    opened by bonyadmitr 8
  • Support dynamic paths

    Support dynamic paths

    The use case for this new flag is to only lint the files that have changed. This could help in larger projects where linting all xib/storyboard files could take a good amount of time. This is also a feature present in other linters like SwiftLint and xiblint.

    opened by jml5qh 7
  • Crash while trying to parse WatchKit app storyboard

    Crash while trying to parse WatchKit app storyboard

    Hi there

    We've got one WatchKit app storyboard, that seems to cause trouble for IBLinter and causes it to crash.

    The error is this:

    Fatal error: parse error /path/to/project/WatchKitApp/Base.lproj/Interface.storyboard: XML Element Error: Incorrect key ["archive"]: file /Users/travis/build/IBDecodable/IBLinter/Sources/IBLinterKit/Validator.swift, line 36

    The storyboard renders in Xcode properly, I've checked it with xmllint and it reported no errors. I can't even find a key called "archived" inside storyboard XML file 🤔

    not sure what's the root cause.

    Out of curiosity, I've removed everything from the storyboard and only this was left:

    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder.WatchKit.Storyboard" version="3.0" toolsVersion="14460.31" targetRuntime="watchKit" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
    
    </document>
    

    still causes the same crash.

    bug 
    opened by mgrebenets 6
  • CocoaPods problem

    CocoaPods problem

    If IBLinter was installed as pod, an empty line is displayed instead of warnings and errors. If IBLinter was installed as brew, it shows warnings and errors.

    opened by emelyanovkirill 5
  • Add support validating placeholder and viewController module

    Add support validating placeholder and viewController module

    This PR adds support validating module of a placeholder or viewController. Currently we are using this tool, but I think we need to validate module in a placeholder or a ViewController.

    This PR also update the related tests.

    opened by rb-de0 5
  • Adds rules to keep

    Adds rules to keep "View as" device

    This PR is to add rules to keep "View as" device for files as specific one. "View as" is useful to confirm that constraints are working correctly on any types of devices. But sometimes we got unnecessary difference for .storyboard unexpectedly when it is left as changed from previous commit. This unexpected difference makes management of .storyboard files more complex. So I consider that it is useful to keep "View as" device at least on commits.

    opened by shosokawa 5
  • Error for custom class seems incorrect

    Error for custom class seems incorrect

    My storyboard has been working just fine but IBLinter reports

    Resources/Base.lproj/Main.storyboard::: error: custom class name 'MainMenuController' should be 'Main' 
    Resources/Base.lproj/Main.storyboard::: error: custom class name 'GameScreenController' should be 'Main' 
    Resources/Base.lproj/Main.storyboard::: error: custom class name 'InfoDialogController' should be 'Main' 
    

    I assume it is suggesting the name of the file. I don’t understand why you can’t have multiple UIViewController subclasses in a storyboard.

    opened by alakoring 5
  • feat: reuse_identifier rule support UICollectionReusableView

    feat: reuse_identifier rule support UICollectionReusableView

    Hi @kateinoigakukun and @phimage.

    Latest IBDecodable supported decode feature of UICollectionReusableView. This PR use it to support UICollectionReusableView in reuse_identifier rule.

    ~NOTE: IBDecodable not yet released as tagged version, I'll change back package dependency files after the release. That is reason I add "WIP" to PR title, but all other work are finished please review except it~ 0.2.0 is not available 👍

    Detail changes description

    • reuse_identifier rule support UICollectionReusableView.
    • fixed unit test.
    • modify storyboard fixture resource to test header and footer UICollectionReusableView.
    opened by r-plus 4
  • add reporting in XML checkstyle format

    add reporting in XML checkstyle format

    as this project is inspired by Swiftlint - it could be easily integrated into Jenkins CI with Warnings NG Plugin when using checkstyle XML report export.

    Is it possible to add this to IBLinter?

    opened by nysander 4
  • Swift Package Manager Plugin

    Swift Package Manager Plugin

    I don't see a Swift Package Manager Plugin to run IBLinter like there is now for SwiftLint and SwiftGen. I'd like to get this working for my project. Before I start on this in a couple days, has anyone already attempted it or in progress?

    I would implement is as a PR to IBLinter adding directly to the existing Package.swift as done in the SwiftLint project. If you would prefer a separate project as done for SwiftGen I'd be happy to discuss the goals.

    opened by briancordanyoung 2
  • Reporters should print violation rule identifier

    Reporters should print violation rule identifier

    Violation messages reported by reporters don't include the violation identifier. Once such an identifier is included, it would be easy to identify and disable enabled by default rules in IBLinter.

    IBLinter reporters don't print a violation rule identifier:

    XXX.xib:0:0: warning: "View as:" should be Unknown device (retina3). Currently it is iPhone XR (retina6_1).

    Swiftlint reporters print a violation rule identifier.

    Rule.swift:44:36: error: Trailing Comma Violation: Collection literals should not have trailing commas. (trailing_comma)

    opened by Adobels 0
  • 'Parse XML error XML Element Error: Incorrect key [

    'Parse XML error XML Element Error: Incorrect key ["archive"]' when analyzing WatchKit storyboards

    I have it integrated as a build step for my iOS app like this:

    if which iblinter >/dev/null; then
      iblinter lint
    else
      echo "warning: IBLinter not installed, download from https://github.com/IBDecodable/IBLinter"
    fi
    

    And it automatically detects all .storyboards and fails with the following errors for the watch kit storyboard.

    WatchKitApp/Base.lproj/Interface.storyboard:0:0: warning: Parse XML error XML Element Error: Incorrect key ["archive"]
    WatchKitApp/Base.lproj/Interface.storyboard:0:0: warning: Parse XML error XML Element Error: Incorrect key ["archive"]
    WatchKitApp/Base.lproj/Interface.storyboard:0:0: warning: Parse XML error XML Element Error: Incorrect key ["archive"]
    WatchKitApp/Base.lproj/Interface.storyboard:0:0: warning: Parse XML error XML Element Error: Incorrect key ["archive"]
    WatchKitApp/Base.lproj/Interface.storyboard:0:0: warning: Parse XML error XML Element Error: Incorrect key ["archive"]
    
    opened by mman 2
  • Can not install in macOS Monterey (12.0 21A5248p)

    Can not install in macOS Monterey (12.0 21A5248p)

    Try to use mint install IBDecodable/IBLinter to install it but failed error msg:

    ▶ mint install IBDecodable/IBLinter
    🌱 Finding latest version of IBLinter
    🌱 Cloning IBLinter 0.4.27
    🌱 Resolving package
    🌱 Building package
    [1/11] Compiling SourceKit SourceKit.m
    [2/11] Compiling Clang_C Clang_C.m
    remark: Incremental compilation has been disabled: it is not compatible with whole module optimizationremark: Incremental compilation has been disabled: it is not compatible with whole module optimizationremark: Incremental compilation has been disabled: it is not compatible with whole module optimization[3/14] Compiling writer.c
    [4/14] Compiling reader.c
    [5/14] Compiling parser.c
    [6/14] Compiling api.c
    [7/14] Compiling emitter.c
    [8/14] Compiling scanner.c
    remark: Incremental compilation has been disabled: it is not compatible with whole module optimizationremark: Incremental compilation has been disabled: it is not compatible with whole module optimization/private/var/folders/gm/6hgr32b973373pdvf4hpfz_xyht1z0/T/mint/github.com_IBDecodable_IBLinter/.build/checkouts/Yams/Sources/Yams/Emitter.swift:338:32: warning: initialization of 'UnsafeMutablePointer<yaml_version_directive_t>' (aka 'UnsafeMutablePointer<yaml_version_directive_s>') results in a dangling pointer
                versionDirective = UnsafeMutablePointer(&versionDirectiveValue)
                                   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /private/var/folders/gm/6hgr32b973373pdvf4hpfz_xyht1z0/T/mint/github.com_IBDecodable_IBLinter/.build/checkouts/Yams/Sources/Yams/Emitter.swift:338:53: note: implicit argument conversion from 'yaml_version_directive_t' (aka 'yaml_version_directive_s') to 'UnsafeMutablePointer<yaml_version_directive_t>' (aka 'UnsafeMutablePointer<yaml_version_directive_s>') produces a pointer valid only for the duration of the call to 'init(_:)'
                versionDirective = UnsafeMutablePointer(&versionDirectiveValue)
                                                        ^~~~~~~~~~~~~~~~~~~~~~
    /private/var/folders/gm/6hgr32b973373pdvf4hpfz_xyht1z0/T/mint/github.com_IBDecodable_IBLinter/.build/checkouts/Yams/Sources/Yams/Emitter.swift:338:53: note: use 'withUnsafeMutablePointer' in order to explicitly convert argument to pointer valid for a defined scope
                versionDirective = UnsafeMutablePointer(&versionDirectiveValue)
                                                        ^
    remark: Incremental compilation has been disabled: it is not compatible with whole module optimization/private/var/folders/gm/6hgr32b973373pdvf4hpfz_xyht1z0/T/mint/github.com_IBDecodable_IBLinter/.build/checkouts/SourceKitten/Source/SourceKittenFramework/Request.swift:251:58: error: cannot convert value of type 'Int' to expected dictionary value type 'Int64'
                        "key.editor.format.usetabs": useTabs ? 1 : 0
                                                             ^
    🌱 Encountered error during "swift build -c release -Xswiftc -target -Xswiftc x86_64-apple-macosx12.0". Use --verbose to see full output
    🌱  Failed to build IBLinter 0.4.27 with SPM
    

    Please Help

    opened by angelmic 1
Releases(0.5.0)
Owner
IBDecodable
IBDecodable
A tool for Swift code modification intermediating between code generation and formatting.

swift-mod A tool for Swift code modification intermediating between code generation and formatting. Overview swift-mod is a tool for Swift code modifi

Ryo Aoyama 95 Nov 3, 2022
A command-line tool and Xcode Extension for formatting Swift code

Table of Contents What? Why? How? Command-line tool Xcode source editor extension Xcode build phase Via Applescript VSCode plugin Sublime Text plugin

Nick Lockwood 6.3k Jan 8, 2023
A tool to enforce Swift style and conventions.

SwiftLint A tool to enforce Swift style and conventions, loosely based on the now archived GitHub Swift Style Guide. SwiftLint enforces the style guid

Realm 16.9k Jan 9, 2023
iOS tool that helps with profiling iOS Memory usage.

FBMemoryProfiler An iOS library providing developer tools for browsing objects in memory over time, using FBAllocationTracker and FBRetainCycleDetecto

Facebook Archive 3.4k Dec 7, 2022
A static source code analysis tool to improve quality and reduce defects for C, C++ and Objective-C

OCLint - https://oclint.org OCLint is a static code analysis tool for improving quality and reducing defects by inspecting C, C++ and Objective-C code

The OCLint Static Code Analysis Tool 3.6k Dec 29, 2022
Simple iOS app blackbox assessment tool. Powered by frida.re and vuejs.

Discontinued Project This project has been discontinued. Please use the new Grapefruit #74 frida@14 compatibility issues frida@14 introduces lots of b

Chaitin Tech 1.6k Dec 16, 2022
Cross-platform static analyzer and linter for Swift.

Wiki • Installation • Usage • Features • Developers • License Tailor is a cross-platform static analysis and lint tool for source code written in Appl

Sleekbyte 1.4k Dec 19, 2022
Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.

Design and prototype customized UI, interaction, navigation, transition and animation for App Store ready Apps in Interface Builder with IBAnimatable.

IBAnimatable 8.6k Jan 2, 2023
Localize your views directly in Interface Builder with IBLocalizable

Localize your views easily in Interface Builder with IBLocalizable. With IBLocalizable, you can localize your views in Interface Builder easily. Simpl

Chris Jimenez 461 Dec 29, 2022
💊 An iOS switch control implemented in Swift with full Interface Builder support

' :::=== ::: === === ::: :::==== :::===== ::: === ' ::: ::: === === ::: :::==== ::: ::: === ' ===== === === === === ===

Thanh Pham 145 Dec 7, 2022
Design shapes in Interface Builder

EPShapes Create shapes(Polygons, Stars, Hearts, Arrows) in Interface builder using IBInspectable and IBDesignable Features Design shapes in interface

Praba 390 Dec 27, 2022
Live rendering of UIImageView properties in Interface Builder

TJProfileImage Live rendering of componet’s properties in Interface Builder Features Dashed border Solid border Round corner Circle image Requirements

Tejas Ardeshna 32 Feb 28, 2022
A Custom UIButton with Centralised Styling and common styles available in Interface Builder

DesignableButton DesignableButton is a UIButton subclass that uses a centralised and reusable styling. In InterfaceBuilder, drag and drop a Designable

Idle Hands Apps 93 Aug 14, 2022
Custom Field component with validation for creating easier form-like UI from interface builder.

#YALField Custom Field component with validation for creating easier form-like UI from interface builder. ##Example Project To run the example project

Yalantis 476 Sep 1, 2022
Introducing with Xcode Storyboard and Interface Builder

I-am-rich Introducing with Xcode Storyboard and Interface Builder Introducing wi

null 0 Dec 17, 2021
An eject button for Interface Builder to generate swift code

Eject Eject is a utility to transition from Interface Builder to programatic view layout. This is done by using code generation to create a .swift fil

Rightpoint 524 Dec 29, 2022
Setup your class structure in Xcode Interface Builder and save() in Parse Server.

ISParseBind With ISParseBind you can save, update and query PFObjects using the power of Xcode Interface Builder resources. https://www.youtube.com/wa

Weni 10 Mar 28, 2022
DevTool - A simple UI and powerful Mac OS application, Such as JSON-Formatting tool, JSON-to-model tool, AppIcon generator, Network-Request tool...

?? ?? ?? A simple UI and powerful Mac OS application. It is a collection of tools commonly used in my development work. Such as JSON-Formatting tool, JSON-to-model tool, AppIcon generator, Network-Request tool...

渠晓友 3 Dec 21, 2022
🌸 Powerful Codable API requests builder and manager for iOS.

This lib is about network requests with blackjack, roulette and craps! Using it you will be able to convert your massive API layer code into an awesom

CodyFire 251 Jan 8, 2023
Simple UIAlertController builder class in Swift.

Kamagari Simple UIAlertController builder class in Swift. Features AlertBuilder class to simply build UIAlertController by using method chaining UIAle

Kazunobu Tasaka 78 Nov 29, 2022