Insanity 0.2.0

Insanity 0.2.0

测试已测试
编程语言语言 Obj-CObjective C
许可 MIT
发布最后发布2016年12月

Krzysztof Zabłocki 管理。



Insanity 0.2.0

什么是 Insanity?

反复做同样的事情,却期待不同的结果。

Swift 是一种美丽的语言,为许多优秀的 iOS 应用提供了动力。不幸的是,它具有非常有限的运行时和没有元编程功能。这导致我们的项目中充满了大量的重复代码模式,可以认为是相同的代码,只是进行了最小的修改。

你有没有?

  • 必须编写 NSCoding 支持?
  • 必须实现 JSON 序列化?
  • 希望值类型可相等且可哈希?
  • 使用枚举来封装解耦的类型?

如果您这样做,您可能发现自己在编写大量重复的代码来处理这些场景,这感觉对吗?

更糟糕的是,如果您为类型添加了新的属性,所有这些实现都必须更新,否则您将陷入 bug 的境地。在这些场景中,通常 编译器不会生成错误信息供您处理,这使得代码易于出错。

Insanity 是一种工具,它可以扫描您的源代码,应用您个人的模板,并为您生成 Swift 代码,让您可以使用元编程技术来节省时间并减少潜在错误。

  • 扫描项目代码。
  • 允许您的模板访问有关项目类型的信息。
  • 生成 Swift 代码。
  • 即时反馈: Insanity 具有内置守护进程支持,允许您在实时与生成的代码并排写入模板。

使用 Insanity 方法有多种好处

  • 减少模板代码的编写并使其轻松遵循 DRY 原则
  • 避免重构时忘记更新模板的风险
  • 提供元编程功能,同时仍然允许编译器确保一切正确。

守护模式运行效果

Daemon demo

所有事物是如何连接的

                                   +--------------+
         Scans code to build AST   |              |  Generates new code
      +---------------------------->   INSANITY   +--------------------------------+
      |                            |              |                                |
      |                            +--^--------^--+                                |
      |                               |        |                                   |
      |                               |        | Reads templates                   |
      |                               |        |                                   |
+-----+------+       +----------------+--+  +--+----------------+        +---------v---------+
|            |       |                   |  |                   |        |                   |
|   Source   |       | Equality Template |  | NSCoding Template |        |  Generated Swift  |
|            |       |                   |  |                   |        |                   |
+-----^------+       +-------------------+  +-------------------+        +-------------------+
      |                                                                            |
      |                                                                            |
      |                                                                            |
      +----------------------------------------------------------------------------+
                              Compiled into your project

示例

用例: 我想知道每个枚举中有多少元素

模板

{% for enum in types.enums %}
extension {{ enum.name }} {
  static var count: Int { return {{ enum.cases.count }} }
}
{% endfor %}

结果

extension AdType {
  static var count: Int { return 2 }
}

用例:`我想为实现特定协议的类型生成相等性'。

模板

{% for type in types.implementing.AutoEquatable %}
extension {{ type.name }}: Equatable {}

func == (lhs: {{ type.name }}, rhs: {{ type.name }}) -> Bool {
    {% for variable in type.storedVariables %} if lhs.{{ variable.name }} != rhs.{{ variable.name }} { return false }
    {% endfor %}
    return true
}
{% endfor %}

结果

extension AccountSectionConfiguration: Equatable {}

func == (lhs: AccountSectionConfiguration, rhs: AccountSectionConfiguration) -> Bool {
     if lhs.status != rhs.status { return false }
     if lhs.user != rhs.user { return false }
     if lhs.entitlements != rhs.entitlements { return false }

    return true
}
用例:`我想列出给定类型中的所有计算变量。

模板

{% for variable in type.VideoViewModel.computedVariables %} {{ variable.name }}: {{ variable.type }}
{% endfor %}

结果

attributedTitle: NSAttributedString
attributedKicker: NSAttributedString
attributedHeadline: NSAttributedString
attributedSummary: NSAttributedString

编写模板

Insanity 模板由 Stencil 提供

确保您利用 Insanity 内置守护进程来使编写模板变得更加愉快:您可以打开模板并与生成的代码并排显示,并实时查看其变化。

有多个方法来访问您的类型

  • type.TypeName=>通过名称访问特定类型
  • types.all=>所有类型(排除协议)
  • types.classes
  • types.structs
  • types.enums
  • types.protocols=>列出所有协议(在项目中定义的协议)
  • types.inheriting.BaseClassOrProtocol=>列出所有从给定基类继承或实现给定协议的类型
  • types.implementing.BaseClassOrProtocol=>与 .inheriting 功能完全相同的便捷别称

对于每种类型,您可以访问以下属性

  • name
  • localName<-父作用域中的名称
  • staticVariables<-静态变量列表
  • variables<-实例变量列表
  • computedVariables<-计算实例变量列表
  • storedVariables<-计算存储变量列表
  • inheritedTypes<-实施/继承此类型的类型名称列表
  • containedTypes<-在此类型中包含的类型列表
  • parentName<-包含类型的父类型列表

Enum 类型建立在常规类型之上,并添加

  • rawType<-枚举原始类型
  • cases<-Enum.Case 列表

Enum.Case 提供

  • name<-名称
  • rawValue<-原始值
  • associatedValues<-AssociatedValue 列表

Enum.Case.AssociatedValue 提供

  • name<-名称
  • type<-相关值的类型

安装

安装

通过 CocoaPods如果您正在使用 CocoaPods,只需将 pod 'Insanity' 添加到您的 Podfile。

这将下载 Insanity 可执行文件和依赖项到 Pods/。您只需要将 $PODS_ROOT/Insanity/bin/Insanity 添加到您的 Script Build Phases。

手动您可以从代码库中克隆它并仅运行 Insanity.xcworkspace

用法

Insanity 是一个命令行工具 Insanity

$ ./Insanity <source> <templates> <output>

参数

  • source - 源 Swift 文件的路径。
  • templates - 模板的路径。文件或目录。
  • output - 输出路径。文件或目录。

选项

  • --watch [默认:false] - 监视模板的变化,并根据需要重新生成。仅适用于特定模板路径(不是目录)。
  • --verbose [默认:false] - 启用忽略实体的详细日志记录

贡献

欢迎并向 Insanity 贡献!

请参阅 贡献指南

通过 GitHub 可以获得贡献者列表。

为了使社区期望清晰,Insanity 采用了贡献者誓言中定义的行为准则。这份文件在许多开源社区中使用,我认为它很好地阐述了我们的价值观。更多信息,请参阅 行为准则

许可

Insanity遵循MIT许可协议。更多信息请见LICENSE

致谢

本工具由以下组件支持

Olivier Halligon指给我一些他的CLI工具设置脚本,非常实用,谢谢!

其他库/工具

如果您想生成与资产相关的逻辑代码,我强烈推荐SwiftGen

请确保检查我的其他库和工具,尤其是

  • KZPlayground - 呈现强大功能Swift和Objective-C的playground
  • KZFileWatchers - 监控本地和远程文件变化的守护进程,用于构建其他开发者工具(Insanity使用它)

您可以在Twitter上关注我的项目更新。